summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2016-11-23 19:09:09 +0900
commit4b4aad7217d3292650e77eec2cf4c198ea9c3b4b (patch)
tree98110734c91668dfdbb126fcc0e15ddbd93738ca /src/mscorlib/src/System/Runtime
parentfa45f57ed55137c75ac870356a1b8f76c84b229c (diff)
downloadcoreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.gz
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.tar.bz2
coreclr-4b4aad7217d3292650e77eec2cf4c198ea9c3b4b.zip
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src/mscorlib/src/System/Runtime')
-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
242 files changed, 32556 insertions, 0 deletions
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
+ }
+}