summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/InteropServices
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Runtime/InteropServices')
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs75
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs1134
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/COMException.cs89
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs21
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs201
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs91
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs245
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs285
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs44
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs28
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs25
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs38
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs60
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs78
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs54
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs48
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs334
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs61
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs67
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs274
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs43
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs50
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs53
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs38
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs79
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs218
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs329
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs49
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs22
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs16
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs38
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/IException.cs83
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs55
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs145
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs37
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs2677
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs64
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs220
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs47
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs1086
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs164
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs53
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs414
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs316
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs772
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs296
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs20
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs140
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs594
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs45
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs26
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs34
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs59
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs35
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs78
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs56
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs329
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs70
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs36
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Variant.cs658
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs36
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs122
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs107
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs240
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs58
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs554
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs457
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs287
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs137
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs123
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs117
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs130
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs167
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs254
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs56
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs586
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs53
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs58
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs323
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs170
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs87
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs140
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs28
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs25
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs112
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs83
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs209
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs187
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs93
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs254
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs75
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs191
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs182
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs67
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs64
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs63
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs117
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs126
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs169
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs46
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs14
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs1334
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs215
140 files changed, 21970 insertions, 0 deletions
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..15872a0e6c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..162cd94901
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs
@@ -0,0 +1,1134 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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
+ }
+
+ [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..756ed3f7e5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..555b2519bd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..2fc5fcbf56
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6e4e99bdf5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..7af80ff7b2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs
@@ -0,0 +1,201 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..b91253d9b5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs
@@ -0,0 +1,91 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5b851f3dae
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs
@@ -0,0 +1,245 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..1b8f965faf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs
@@ -0,0 +1,285 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..748b9d11ba
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..b62cf29eea
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f6c1a9db90
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5ad02da7e2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..8631e287ad
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..91db513494
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..a01895ec4d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..efdc46be35
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e4f527470c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..96f05696a3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..58084f16c2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..7cafcacc34
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..a42d7b04ac
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..657ab66103
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..0e0e36d20f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..1155eecd4f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..4a9904b6c5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs
@@ -0,0 +1,54 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f73dec1b66
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ccd4576910
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs
@@ -0,0 +1,334 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3b13ebab35
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..14f0c87c27
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..d5d4c365e0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f36ab28d61
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs
@@ -0,0 +1,274 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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 occured 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..6fe3bb7df7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..66c9e80039
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..008ee3579b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6940157638
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..b8202f6410
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ea9f8667fa
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs
@@ -0,0 +1,79 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e4ba66c8c3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs
@@ -0,0 +1,218 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c2799e0330
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs
@@ -0,0 +1,329 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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 WIN32
+ InternalFree((IntPtr)(((int)handle) & ~1));
+#else
+ InternalFree((IntPtr)(((long)handle) & ~1L));
+#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 WIN32
+ return new IntPtr(((int)m_handle) & ~1);
+#else
+ return new IntPtr(((long)m_handle) & ~1L);
+#endif
+ }
+
+ internal bool IsPinned()
+ {
+#if WIN32
+ return (((int)m_handle) & 1) != 0;
+#else
+ return (((long)m_handle) & 1) != 0;
+#endif
+ }
+
+ internal void SetIsPinned()
+ {
+#if WIN32
+ m_handle = new IntPtr(((int)m_handle) | 1);
+#else
+ m_handle = new IntPtr(((long)m_handle) | 1L);
+#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..5b7644b521
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ba5d622a0d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6b06b46d6a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e02db98bb3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..b6c057be02
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..314e571187
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs
@@ -0,0 +1,83 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5c5c6cdc88
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ff6d73866d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs
@@ -0,0 +1,145 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ae1f006417
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..81ace87f0a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6eed1af070
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..a46999a004
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs
@@ -0,0 +1,2677 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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);
+ }
+
+ //====================================================================
+ // 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
+ //====================================================================
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RU1")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs);
+
+ [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);
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI2")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+
+ [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);
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI4"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+
+ [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 WIN32
+ return (IntPtr) ReadInt32(ptr, ofs);
+ #else
+ return (IntPtr) ReadInt64(ptr, ofs);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static IntPtr ReadIntPtr(IntPtr ptr, int ofs)
+ {
+ #if WIN32
+ return (IntPtr) ReadInt32(ptr, ofs);
+ #else
+ return (IntPtr) ReadInt64(ptr, ofs);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static IntPtr ReadIntPtr(IntPtr ptr)
+ {
+ #if WIN32
+ return (IntPtr) ReadInt32(ptr, 0);
+ #else
+ return (IntPtr) ReadInt64(ptr, 0);
+ #endif
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI8"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+
+ [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();
+ }
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WU1")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val);
+
+ [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();
+ }
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI2")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val);
+
+ [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();
+ }
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI4")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val);
+
+ [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 WIN32
+ WriteInt32(ptr, ofs, (int)val);
+ #else
+ WriteInt64(ptr, ofs, (long)val);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteIntPtr([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, IntPtr val)
+ {
+ #if WIN32
+ WriteInt32(ptr, ofs, (int)val);
+ #else
+ WriteInt64(ptr, ofs, (long)val);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteIntPtr(IntPtr ptr, IntPtr val)
+ {
+ #if WIN32
+ WriteInt32(ptr, 0, (int)val);
+ #else
+ WriteInt64(ptr, 0, (long)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();
+ }
+ }
+
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI8")]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ public static extern void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val);
+
+ [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(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);
+
+
+ //====================================================================
+ // 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);
+
+ //====================================================================
+ // 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 WIN32
+ numBytes = new UIntPtr(unchecked((uint)cb.ToInt32()));
+#else
+ numBytes = new UIntPtr(unchecked((ulong)cb.ToInt64()));
+#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
+
+ 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
+ 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;
+ }
+
+
+#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 );
+
+ //====================================================================
+ // 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));
+ }
+
+ [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);
+ }
+
+#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..076307feb8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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/NativeMethods.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs
new file mode 100644
index 0000000000..585e7a6b25
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5fbea85516
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs
@@ -0,0 +1,220 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+// Dummy implementations of non-portable interop methods that just throw PlatformNotSupportedException
+
+namespace System.Runtime.InteropServices
+{
+ public static partial class Marshal
+ {
+ [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 void FreeBSTR(System.IntPtr ptr)
+ {
+ 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 string PtrToStringBSTR(System.IntPtr ptr)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [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 System.IntPtr StringToBSTR(string s)
+ {
+ 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..a01061e74a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..9b16a5f866
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6b83e92057
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs
@@ -0,0 +1,1086 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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,new Type[0],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..e7aa9ad062
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs
@@ -0,0 +1,164 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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.MAX_PATH);
+ 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..b7ab8999c8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3185a3d63e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3c6bffb06a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ad63decbb1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs
@@ -0,0 +1,414 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..d839be3897
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs
@@ -0,0 +1,316 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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/TCEAdapterGen/EventItfInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs
new file mode 100644
index 0000000000..52ebd09b80
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..2427a5fb39
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs
@@ -0,0 +1,772 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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, new Type[0], 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, new Type[0], 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, new Type[0], 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..5fde67ff89
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs
@@ -0,0 +1,296 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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, new Type[0], 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..a6e999197b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..87dd52fd21
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs
@@ -0,0 +1,140 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..650af9c4e6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs
@@ -0,0 +1,594 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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.MAX_PATH)
+ 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..c1b44e14f0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs
@@ -0,0 +1,45 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..4fde2a47dd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c70f253bd9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3ffeb25ed0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..1a7a6e52e9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs
@@ -0,0 +1,41 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..9a90dea638
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..93fbcec53c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c74c0b3568
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3fcd279070
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs
@@ -0,0 +1,29 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..4e9eb5ce2f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..60774b8ac4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..8e0108d98e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5ba4851f37
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..476c671e85
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs
@@ -0,0 +1,78 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e5e40a11a7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..aed024f579
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..7d6c89937f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..2978bf9ac8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs
@@ -0,0 +1,329 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..b67347b7e2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c9084f715f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..fbd1b3c15d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs
@@ -0,0 +1,658 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c57ed61054
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..5bc5a7dd22
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs
@@ -0,0 +1,122 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..2f15428ae1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs
@@ -0,0 +1,107 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..fddc7588c2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs
@@ -0,0 +1,240 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..683a7f3327
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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>
+ {
+ 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();
+ }
+ }
+}
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..2cd5cfd20a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs
@@ -0,0 +1,554 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..99c546a392
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs
@@ -0,0 +1,457 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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>, ICustomPropertyProvider
+ {
+ 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();
+ }
+ }
+
+ [Pure]
+ ICustomProperty ICustomPropertyProvider.GetCustomProperty(string name)
+ {
+ // _value should not be null
+ return ICustomPropertyProviderImpl.CreateProperty((object)_value, name);
+ }
+
+ [Pure]
+ ICustomProperty ICustomPropertyProvider.GetIndexedProperty(string name, Type indexParameterType)
+ {
+ // _value should not be null
+ return ICustomPropertyProviderImpl.CreateIndexedProperty((object)_value, name, indexParameterType);
+ }
+
+ [Pure]
+ string ICustomPropertyProvider.GetStringRepresentation()
+ {
+ // _value should not be null
+ return ((object)_value).ToString();
+ }
+
+ Type ICustomPropertyProvider.Type
+ {
+ [Pure]
+ get
+ {
+ // _value should not be null
+ return ((object)_value).GetType();
+ }
+ }
+
+ // 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,
+ IReferenceArray<T>,
+ ICustomPropertyProvider,
+ 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();
+ }
+ }
+
+ [Pure]
+ ICustomProperty ICustomPropertyProvider.GetCustomProperty(string name)
+ {
+ // _value should not be null
+ return ICustomPropertyProviderImpl.CreateProperty((object)_value, name);
+ }
+
+ [Pure]
+ ICustomProperty ICustomPropertyProvider.GetIndexedProperty(string name, Type indexParameterType)
+ {
+ // _value should not be null
+ return ICustomPropertyProviderImpl.CreateIndexedProperty((object)_value, name, indexParameterType);
+ }
+
+ [Pure]
+ string ICustomPropertyProvider.GetStringRepresentation()
+ {
+ // _value should not be null
+ return ((object)_value).ToString();
+ }
+
+ Type ICustomPropertyProvider.Type
+ {
+ [Pure]
+ get
+ {
+ // _value should not be null
+ return ((object)_value).GetType();
+ }
+ }
+
+ //
+ // 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;
+ }
+ }
+
+ // 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..a23d484a6f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs
@@ -0,0 +1,287 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..01a6bc81de
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
@@ -0,0 +1,137 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6c56c10c46
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..1dcdeadcc3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f8e4ea555b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs
@@ -0,0 +1,130 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..9c203bcefa
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs
@@ -0,0 +1,167 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e9126d122a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..91b123bee7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
@@ -0,0 +1,254 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..85377187d2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..28841fe661
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..aa7ea5fdb2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..51c62618c5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs
@@ -0,0 +1,586 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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
+{
+ [ComImport]
+ [Guid("7C925755-3E48-42B4-8677-76372267033F")]
+ [WindowsRuntimeImport]
+ internal interface ICustomPropertyProvider
+ {
+ [Pure]
+ ICustomProperty GetCustomProperty(string name);
+
+ [Pure]
+ ICustomProperty GetIndexedProperty(string name, Type indexParameterType);
+
+ [Pure]
+ string GetStringRepresentation();
+
+ Type Type
+ {
+ [Pure]
+ get;
+ }
+ }
+
+ //
+ // 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);
+
+ // 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);
+
+ // 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)
+ {
+ 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,
+ ICustomPropertyProvider,
+ 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);
+ }
+
+ //
+ // ICustomPropertyProvider implementation
+ //
+ ICustomProperty ICustomPropertyProvider.GetCustomProperty(string name)
+ {
+ return ICustomPropertyProviderImpl.CreateProperty(_target, name);
+ }
+
+ ICustomProperty ICustomPropertyProvider.GetIndexedProperty(string name, Type indexParameterType)
+ {
+ return ICustomPropertyProviderImpl.CreateIndexedProperty(_target, name, indexParameterType);
+ }
+
+ string ICustomPropertyProvider.GetStringRepresentation()
+ {
+ return WindowsRuntime.IStringableHelper.ToString(_target);
+ }
+
+ Type ICustomPropertyProvider.Type
+ {
+ get
+ {
+ return _target.GetType();
+ }
+ }
+
+ //
+ // 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..e0fad0c4ee
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..a663de248e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs
@@ -0,0 +1,53 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..72cf85cd3e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs
@@ -0,0 +1,58 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f26d50f953
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
@@ -0,0 +1,323 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..792e6c1550
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs
@@ -0,0 +1,170 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..65feecc447
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..719bddc67e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs
@@ -0,0 +1,140 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..864f6f5038
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..8bd4502fe7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..99952e5825
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs
@@ -0,0 +1,112 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..ceba967db0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs
@@ -0,0 +1,83 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..c1656ce7f8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs
@@ -0,0 +1,209 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e9fbdcf960
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs
@@ -0,0 +1,187 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..f89d9a7e90
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs
@@ -0,0 +1,93 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..1087fe2154
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs
@@ -0,0 +1,254 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..6ff37cbc5e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..3558bf3b2a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs
@@ -0,0 +1,191 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..d5c28c4abf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs
@@ -0,0 +1,182 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..583903acf8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs
@@ -0,0 +1,67 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..bf011955c2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+#if WIN64
+ [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..23f8539f84
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..0139fab27a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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)
+ {
+ // 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..91d9346604
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs
@@ -0,0 +1,126 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..4fed70c63f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs
@@ -0,0 +1,169 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..eea37b3bdc
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..e057846e2f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs
@@ -0,0 +1,14 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..12cf107a47
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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..dbf1a8a1f1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
@@ -0,0 +1,1334 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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 occured 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..5fe3bdde08
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs
@@ -0,0 +1,215 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license 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>();
+ }
+ }
+}