diff options
Diffstat (limited to 'src/mscorlib/src/System/Runtime')
242 files changed, 32556 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs new file mode 100644 index 0000000000..b0010fd7bd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +namespace System.Runtime.CompilerServices +{ + using System; + + [AttributeUsage(AttributeTargets.Field)] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class AccessedThroughPropertyAttribute : Attribute + { + private readonly string propertyName; + + public AccessedThroughPropertyAttribute(string propertyName) + { + this.propertyName = propertyName; + } + + public string PropertyName + { + get + { + return propertyName; + } + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs new file mode 100644 index 0000000000..c021353475 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.CompilerServices { + + using System; + + // NOTE TO DEVELOPERS: These classes are used by ALink (the assembly linker). + // They're used for metadata tokens for making multi-module assemblies. + // Do not randomly touch these classes. + [System.Runtime.CompilerServices.FriendAccessAllowed] + internal sealed class AssemblyAttributesGoHere + { + + internal AssemblyAttributesGoHere() + { + } + } + [System.Runtime.CompilerServices.FriendAccessAllowed] + internal sealed class AssemblyAttributesGoHereS + { + internal AssemblyAttributesGoHereS() + { + } + } + [System.Runtime.CompilerServices.FriendAccessAllowed] + internal sealed class AssemblyAttributesGoHereM + { + internal AssemblyAttributesGoHereM() + { + } + } + [System.Runtime.CompilerServices.FriendAccessAllowed] + internal sealed class AssemblyAttributesGoHereSM + { + internal AssemblyAttributesGoHereSM() + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs new file mode 100644 index 0000000000..5251122629 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +namespace System.Runtime.CompilerServices +{ + + using System; + using System.Runtime.InteropServices; + + /* + NGenHint is not supported in Whidbey + + [Serializable] + public enum NGenHint + { + Default = 0x0000, // No preference specified + + Eager = 0x0001, // NGen at install time + Lazy = 0x0002, // NGen after install time + Never = 0x0003, // Assembly should not be ngened + } + */ + + [Serializable] + public enum LoadHint + { + Default = 0x0000, // No preference specified + + Always = 0x0001, // Dependency is always loaded + Sometimes = 0x0002, // Dependency is sometimes loaded + //Never = 0x0003, // Dependency is never loaded + } + + [Serializable] + [AttributeUsage(AttributeTargets.Assembly)] + public sealed class DefaultDependencyAttribute : Attribute + { + private LoadHint loadHint; + + public DefaultDependencyAttribute ( + LoadHint loadHintArgument + ) + { + loadHint = loadHintArgument; + } + + public LoadHint LoadHint + { + get + { + return loadHint; + } + } + } + + +[Serializable] +[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public sealed class DependencyAttribute : Attribute + { + private String dependentAssembly; + private LoadHint loadHint; + + public DependencyAttribute ( + String dependentAssemblyArgument, + LoadHint loadHintArgument + ) + { + dependentAssembly = dependentAssemblyArgument; + loadHint = loadHintArgument; + } + + public String DependentAssembly + { + get + { + return dependentAssembly; + } + } + + public LoadHint LoadHint + { + get + { + return loadHint; + } + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs new file mode 100644 index 0000000000..05850605b8 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -0,0 +1,1187 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// +// +// +// Compiler-targeted types that build tasks for use as the return types of asynchronous methods. +// +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using System.Runtime.ExceptionServices; +using System.Security; +using System.Security.Permissions; +using System.Threading; +using System.Threading.Tasks; + +#if FEATURE_COMINTEROP +using System.Runtime.InteropServices.WindowsRuntime; +#endif // FEATURE_COMINTEROP + +namespace System.Runtime.CompilerServices +{ + /// <summary> + /// Provides a builder for asynchronous methods that return void. + /// This type is intended for compiler use only. + /// </summary> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct AsyncVoidMethodBuilder + { + /// <summary>The synchronization context associated with this operation.</summary> + private SynchronizationContext m_synchronizationContext; + /// <summary>State related to the IAsyncStateMachine.</summary> + private AsyncMethodBuilderCore m_coreState; // mutable struct: must not be readonly + /// <summary>Task used for debugging and logging purposes only. Lazily initialized.</summary> + private Task m_task; + + /// <summary>Initializes a new <see cref="AsyncVoidMethodBuilder"/>.</summary> + /// <returns>The initialized <see cref="AsyncVoidMethodBuilder"/>.</returns> + public static AsyncVoidMethodBuilder Create() + { + // Capture the current sync context. If there isn't one, use the dummy s_noContextCaptured + // instance; this allows us to tell the state of no captured context apart from the state + // of an improperly constructed builder instance. + SynchronizationContext sc = SynchronizationContext.CurrentNoFlow; + if (sc != null) + sc.OperationStarted(); + return new AsyncVoidMethodBuilder() { m_synchronizationContext = sc }; + } + + /// <summary>Initiates the builder's execution with the associated state machine.</summary> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="stateMachine">The state machine instance, passed by reference.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception> + [SecuritySafeCritical] + [DebuggerStepThrough] + public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine + { + // See comment on AsyncMethodBuilderCore.Start + // AsyncMethodBuilderCore.Start(ref stateMachine); + + if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + Contract.EndContractBlock(); + + // Run the MoveNext method within a copy-on-write ExecutionContext scope. + // This allows us to undo any ExecutionContext changes made in MoveNext, + // so that they won't "leak" out of the first await. + + Thread currentThread = Thread.CurrentThread; + ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher); + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs); + stateMachine.MoveNext(); + } + finally + { + ecs.Undo(currentThread); + } + } + + /// <summary>Associates the builder with the state machine it represents.</summary> + /// <param name="stateMachine">The heap-allocated state machine object.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception> + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + m_coreState.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + public void AwaitOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine + { + try + { + AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; + var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); + Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + + // If this is our first await, such that we've not yet boxed the state machine, do so now. + if (m_coreState.m_stateMachine == null) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Task.Id, "Async: " + stateMachine.GetType().Name, 0); + + // Box the state machine, then tell the boxed instance to call back into its own builder, + // so we can cache the boxed reference. NOTE: The language compiler may choose to use + // a class instead of a struct for the state machine for debugging purposes; in such cases, + // the stateMachine will already be an object. + m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, null); + } + + awaiter.OnCompleted(continuation); + } + catch (Exception exc) + { + // Prevent exceptions from leaking to the call site, which could + // then allow multiple flows of execution through the same async method + // if the awaiter had already scheduled the continuation by the time + // the exception was thrown. We propagate the exception on the + // ThreadPool because we can trust it to not throw, unlike + // if we were to go to a user-supplied SynchronizationContext, + // whose Post method could easily throw. + AsyncMethodBuilderCore.ThrowAsync(exc, targetContext: null); + } + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + [SecuritySafeCritical] + public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine + { + try + { + AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; + var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); + Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + + // If this is our first await, such that we've not yet boxed the state machine, do so now. + if (m_coreState.m_stateMachine == null) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Task.Id, "Async: " + stateMachine.GetType().Name, 0); + + // Box the state machine, then tell the boxed instance to call back into its own builder, + // so we can cache the boxed reference. NOTE: The language compiler may choose to use + // a class instead of a struct for the state machine for debugging purposes; in such cases, + // the stateMachine will already be an object. + m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, null); + } + + awaiter.UnsafeOnCompleted(continuation); + } + catch (Exception e) + { + AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null); + } + } + + /// <summary>Completes the method builder successfully.</summary> + public void SetResult() + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Task.Id, AsyncCausalityStatus.Completed); + + if (m_synchronizationContext != null) + { + NotifySynchronizationContextOfCompletion(); + } + } + + /// <summary>Faults the method builder with an exception.</summary> + /// <param name="exception">The exception that is the cause of this fault.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception> + public void SetException(Exception exception) + { + if (exception == null) throw new ArgumentNullException("exception"); + Contract.EndContractBlock(); + + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Task.Id, AsyncCausalityStatus.Error); + + if (m_synchronizationContext != null) + { + // If we captured a synchronization context, Post the throwing of the exception to it + // and decrement its outstanding operation count. + try + { + AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: m_synchronizationContext); + } + finally + { + NotifySynchronizationContextOfCompletion(); + } + } + else + { + // Otherwise, queue the exception to be thrown on the ThreadPool. This will + // result in a crash unless legacy exception behavior is enabled by a config + // file or a CLR host. + AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: null); + } + } + + /// <summary>Notifies the current synchronization context that the operation completed.</summary> + private void NotifySynchronizationContextOfCompletion() + { + Contract.Assert(m_synchronizationContext != null, "Must only be used with a non-null context."); + try + { + m_synchronizationContext.OperationCompleted(); + } + catch (Exception exc) + { + // If the interaction with the SynchronizationContext goes awry, + // fall back to propagating on the ThreadPool. + AsyncMethodBuilderCore.ThrowAsync(exc, targetContext: null); + } + } + + // This property lazily instantiates the Task in a non-thread-safe manner. + private Task Task + { + get + { + if (m_task == null) m_task = new Task(); + return m_task; + } + } + + /// <summary> + /// Gets an object that may be used to uniquely identify this builder to the debugger. + /// </summary> + /// <remarks> + /// This property lazily instantiates the ID in a non-thread-safe manner. + /// It must only be used by the debugger and AsyncCausalityTracer in a single-threaded manner. + /// </remarks> + private object ObjectIdForDebugger { get { return this.Task; } } + } + + /// <summary> + /// Provides a builder for asynchronous methods that return <see cref="System.Threading.Tasks.Task"/>. + /// This type is intended for compiler use only. + /// </summary> + /// <remarks> + /// AsyncTaskMethodBuilder is a value type, and thus it is copied by value. + /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed, + /// or else the copies may end up building distinct Task instances. + /// </remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct AsyncTaskMethodBuilder + { + /// <summary>A cached VoidTaskResult task used for builders that complete synchronously.</summary> + private readonly static Task<VoidTaskResult> s_cachedCompleted = AsyncTaskMethodBuilder<VoidTaskResult>.s_defaultResultTask; + + /// <summary>The generic builder object to which this non-generic instance delegates.</summary> + private AsyncTaskMethodBuilder<VoidTaskResult> m_builder; // mutable struct: must not be readonly + + /// <summary>Initializes a new <see cref="AsyncTaskMethodBuilder"/>.</summary> + /// <returns>The initialized <see cref="AsyncTaskMethodBuilder"/>.</returns> + public static AsyncTaskMethodBuilder Create() + { + return default(AsyncTaskMethodBuilder); + // Note: If ATMB<T>.Create is modified to do any initialization, this + // method needs to be updated to do m_builder = ATMB<T>.Create(). + } + + /// <summary>Initiates the builder's execution with the associated state machine.</summary> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="stateMachine">The state machine instance, passed by reference.</param> + [SecuritySafeCritical] + [DebuggerStepThrough] + public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine + { + // See comment on AsyncMethodBuilderCore.Start + // AsyncMethodBuilderCore.Start(ref stateMachine); + + if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + Contract.EndContractBlock(); + + // Run the MoveNext method within a copy-on-write ExecutionContext scope. + // This allows us to undo any ExecutionContext changes made in MoveNext, + // so that they won't "leak" out of the first await. + + Thread currentThread = Thread.CurrentThread; + ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher); + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs); + stateMachine.MoveNext(); + } + finally + { + ecs.Undo(currentThread); + } + } + + /// <summary>Associates the builder with the state machine it represents.</summary> + /// <param name="stateMachine">The heap-allocated state machine object.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception> + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + m_builder.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + public void AwaitOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine + { + m_builder.AwaitOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine); + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine + { + m_builder.AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine); + } + + /// <summary>Gets the <see cref="System.Threading.Tasks.Task"/> for this builder.</summary> + /// <returns>The <see cref="System.Threading.Tasks.Task"/> representing the builder's asynchronous operation.</returns> + /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception> + public Task Task { get { return m_builder.Task; } } + + /// <summary> + /// Completes the <see cref="System.Threading.Tasks.Task"/> in the + /// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state. + /// </summary> + /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception> + /// <exception cref="System.InvalidOperationException">The task has already completed.</exception> + public void SetResult() + { + // Accessing AsyncTaskMethodBuilder.s_cachedCompleted is faster than + // accessing AsyncTaskMethodBuilder<T>.s_defaultResultTask. + m_builder.SetResult(s_cachedCompleted); + } + + /// <summary> + /// Completes the <see cref="System.Threading.Tasks.Task"/> in the + /// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception. + /// </summary> + /// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception> + /// <exception cref="System.InvalidOperationException">The task has already completed.</exception> + public void SetException(Exception exception) { m_builder.SetException(exception); } + + /// <summary> + /// Called by the debugger to request notification when the first wait operation + /// (await, Wait, Result, etc.) on this builder's task completes. + /// </summary> + /// <param name="enabled"> + /// true to enable notification; false to disable a previously set notification. + /// </param> + internal void SetNotificationForWaitCompletion(bool enabled) + { + m_builder.SetNotificationForWaitCompletion(enabled); + } + + /// <summary> + /// Gets an object that may be used to uniquely identify this builder to the debugger. + /// </summary> + /// <remarks> + /// This property lazily instantiates the ID in a non-thread-safe manner. + /// It must only be used by the debugger and tracing pruposes, and only in a single-threaded manner + /// when no other threads are in the middle of accessing this property or this.Task. + /// </remarks> + private object ObjectIdForDebugger { get { return this.Task; } } + } + + /// <summary> + /// Provides a builder for asynchronous methods that return <see cref="System.Threading.Tasks.Task{TResult}"/>. + /// This type is intended for compiler use only. + /// </summary> + /// <remarks> + /// AsyncTaskMethodBuilder{TResult} is a value type, and thus it is copied by value. + /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed, + /// or else the copies may end up building distinct Task instances. + /// </remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct AsyncTaskMethodBuilder<TResult> + { + /// <summary>A cached task for default(TResult).</summary> + internal readonly static Task<TResult> s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)); + + // WARNING: For performance reasons, the m_task field is lazily initialized. + // For correct results, the struct AsyncTaskMethodBuilder<TResult> must + // always be used from the same location/copy, at least until m_task is + // initialized. If that guarantee is broken, the field could end up being + // initialized on the wrong copy. + + /// <summary>State related to the IAsyncStateMachine.</summary> + private AsyncMethodBuilderCore m_coreState; // mutable struct: must not be readonly + /// <summary>The lazily-initialized built task.</summary> + private Task<TResult> m_task; // lazily-initialized: must not be readonly + + /// <summary>Initializes a new <see cref="AsyncTaskMethodBuilder"/>.</summary> + /// <returns>The initialized <see cref="AsyncTaskMethodBuilder"/>.</returns> + public static AsyncTaskMethodBuilder<TResult> Create() + { + return default(AsyncTaskMethodBuilder<TResult>); + // NOTE: If this method is ever updated to perform more initialization, + // ATMB.Create must also be updated to call this Create method. + } + + /// <summary>Initiates the builder's execution with the associated state machine.</summary> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="stateMachine">The state machine instance, passed by reference.</param> + [SecuritySafeCritical] + [DebuggerStepThrough] + public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine + { + // See comment on AsyncMethodBuilderCore.Start + // AsyncMethodBuilderCore.Start(ref stateMachine); + + if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + Contract.EndContractBlock(); + + // Run the MoveNext method within a copy-on-write ExecutionContext scope. + // This allows us to undo any ExecutionContext changes made in MoveNext, + // so that they won't "leak" out of the first await. + + Thread currentThread = Thread.CurrentThread; + ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher); + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs); + stateMachine.MoveNext(); + } + finally + { + ecs.Undo(currentThread); + } + } + + /// <summary>Associates the builder with the state machine it represents.</summary> + /// <param name="stateMachine">The heap-allocated state machine object.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception> + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + m_coreState.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + public void AwaitOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine + { + try + { + AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; + var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); + Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + + // If this is our first await, such that we've not yet boxed the state machine, do so now. + if (m_coreState.m_stateMachine == null) + { + // Force the Task to be initialized prior to the first suspending await so + // that the original stack-based builder has a reference to the right Task. + var builtTask = this.Task; + + // Box the state machine, then tell the boxed instance to call back into its own builder, + // so we can cache the boxed reference. NOTE: The language compiler may choose to use + // a class instead of a struct for the state machine for debugging purposes; in such cases, + // the stateMachine will already be an object. + m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, builtTask); + } + + awaiter.OnCompleted(continuation); + } + catch (Exception e) + { + AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null); + } + } + + /// <summary> + /// Schedules the specified state machine to be pushed forward when the specified awaiter completes. + /// </summary> + /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="awaiter">The awaiter.</param> + /// <param name="stateMachine">The state machine.</param> + [SecuritySafeCritical] + public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( + ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine + { + try + { + AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; + var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); + Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action."); + + // If this is our first await, such that we've not yet boxed the state machine, do so now. + if (m_coreState.m_stateMachine == null) + { + // Force the Task to be initialized prior to the first suspending await so + // that the original stack-based builder has a reference to the right Task. + var builtTask = this.Task; + + // Box the state machine, then tell the boxed instance to call back into its own builder, + // so we can cache the boxed reference. NOTE: The language compiler may choose to use + // a class instead of a struct for the state machine for debugging purposes; in such cases, + // the stateMachine will already be an object. + m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, builtTask); + } + + awaiter.UnsafeOnCompleted(continuation); + } + catch (Exception e) + { + AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null); + } + } + + /// <summary>Gets the <see cref="System.Threading.Tasks.Task{TResult}"/> for this builder.</summary> + /// <returns>The <see cref="System.Threading.Tasks.Task{TResult}"/> representing the builder's asynchronous operation.</returns> + public Task<TResult> Task + { + get + { + // Get and return the task. If there isn't one, first create one and store it. + var task = m_task; + if (task == null) { m_task = task = new Task<TResult>(); } + return task; + } + } + + /// <summary> + /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the + /// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state with the specified result. + /// </summary> + /// <param name="result">The result to use to complete the task.</param> + /// <exception cref="System.InvalidOperationException">The task has already completed.</exception> + public void SetResult(TResult result) + { + // Get the currently stored task, which will be non-null if get_Task has already been accessed. + // If there isn't one, get a task and store it. + var task = m_task; + if (task == null) + { + m_task = GetTaskForResult(result); + Contract.Assert(m_task != null, "GetTaskForResult should never return null"); + } + // Slow path: complete the existing task. + else + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, task.Id, AsyncCausalityStatus.Completed); + + //only log if we have a real task that was previously created + if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) + { + System.Threading.Tasks.Task.RemoveFromActiveTasks(task.Id); + } + + if (!task.TrySetResult(result)) + { + throw new InvalidOperationException(Environment.GetResourceString("TaskT_TransitionToFinal_AlreadyCompleted")); + } + } + } + + /// <summary> + /// Completes the builder by using either the supplied completed task, or by completing + /// the builder's previously accessed task using default(TResult). + /// </summary> + /// <param name="completedTask">A task already completed with the value default(TResult).</param> + /// <exception cref="System.InvalidOperationException">The task has already completed.</exception> + internal void SetResult(Task<TResult> completedTask) + { + Contract.Requires(completedTask != null, "Expected non-null task"); + Contract.Requires(completedTask.Status == TaskStatus.RanToCompletion, "Expected a successfully completed task"); + + // Get the currently stored task, which will be non-null if get_Task has already been accessed. + // If there isn't one, store the supplied completed task. + var task = m_task; + if (task == null) + { + m_task = completedTask; + } + else + { + // Otherwise, complete the task that's there. + SetResult(default(TResult)); + } + } + + /// <summary> + /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the + /// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception. + /// </summary> + /// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The task has already completed.</exception> + public void SetException(Exception exception) + { + if (exception == null) throw new ArgumentNullException("exception"); + Contract.EndContractBlock(); + + + var task = m_task; + if (task == null) + { + // Get the task, forcing initialization if it hasn't already been initialized. + task = this.Task; + } + + // If the exception represents cancellation, cancel the task. Otherwise, fault the task. + var oce = exception as OperationCanceledException; + bool successfullySet = oce != null ? + task.TrySetCanceled(oce.CancellationToken, oce) : + task.TrySetException(exception); + + // Unlike with TaskCompletionSource, we do not need to spin here until m_task is completed, + // since AsyncTaskMethodBuilder.SetException should not be immediately followed by any code + // that depends on the task having completely completed. Moreover, with correct usage, + // SetResult or SetException should only be called once, so the Try* methods should always + // return true, so no spinning would be necessary anyway (the spinning in TCS is only relevant + // if another thread completes the task first). + + if (!successfullySet) + { + throw new InvalidOperationException(Environment.GetResourceString("TaskT_TransitionToFinal_AlreadyCompleted")); + } + } + + /// <summary> + /// Called by the debugger to request notification when the first wait operation + /// (await, Wait, Result, etc.) on this builder's task completes. + /// </summary> + /// <param name="enabled"> + /// true to enable notification; false to disable a previously set notification. + /// </param> + /// <remarks> + /// This should only be invoked from within an asynchronous method, + /// and only by the debugger. + /// </remarks> + internal void SetNotificationForWaitCompletion(bool enabled) + { + // Get the task (forcing initialization if not already initialized), and set debug notification + this.Task.SetNotificationForWaitCompletion(enabled); + } + + /// <summary> + /// Gets an object that may be used to uniquely identify this builder to the debugger. + /// </summary> + /// <remarks> + /// This property lazily instantiates the ID in a non-thread-safe manner. + /// It must only be used by the debugger and tracing purposes, and only in a single-threaded manner + /// when no other threads are in the middle of accessing this property or this.Task. + /// </remarks> + private object ObjectIdForDebugger { get { return this.Task; } } + + /// <summary> + /// Gets a task for the specified result. This will either + /// be a cached or new task, never null. + /// </summary> + /// <param name="result">The result for which we need a task.</param> + /// <returns>The completed task containing the result.</returns> + [SecuritySafeCritical] // for JitHelpers.UnsafeCast + private Task<TResult> GetTaskForResult(TResult result) + { + Contract.Ensures( + EqualityComparer<TResult>.Default.Equals(result, Contract.Result<Task<TResult>>().Result), + "The returned task's Result must return the same value as the specified result value."); + + // The goal of this function is to be give back a cached task if possible, + // or to otherwise give back a new task. To give back a cached task, + // we need to be able to evaluate the incoming result value, and we need + // to avoid as much overhead as possible when doing so, as this function + // is invoked as part of the return path from every async method. + // Most tasks won't be cached, and thus we need the checks for those that are + // to be as close to free as possible. This requires some trickiness given the + // lack of generic specialization in .NET. + // + // Be very careful when modifying this code. It has been tuned + // to comply with patterns recognized by both 32-bit and 64-bit JITs. + // If changes are made here, be sure to look at the generated assembly, as + // small tweaks can have big consequences for what does and doesn't get optimized away. + // + // Note that this code only ever accesses a static field when it knows it'll + // find a cached value, since static fields (even if readonly and integral types) + // require special access helpers in this NGEN'd and domain-neutral. + + if (null != (object)default(TResult)) // help the JIT avoid the value type branches for ref types + { + // Special case simple value types: + // - Boolean + // - Byte, SByte + // - Char + // - Decimal + // - Int32, UInt32 + // - Int64, UInt64 + // - Int16, UInt16 + // - IntPtr, UIntPtr + // As of .NET 4.5, the (Type)(object)result pattern used below + // is recognized and optimized by both 32-bit and 64-bit JITs. + + // For Boolean, we cache all possible values. + if (typeof(TResult) == typeof(Boolean)) // only the relevant branches are kept for each value-type generic instantiation + { + Boolean value = (Boolean)(object)result; + Task<Boolean> task = value ? AsyncTaskCache.TrueTask : AsyncTaskCache.FalseTask; + return JitHelpers.UnsafeCast<Task<TResult>>(task); // UnsafeCast avoids type check we know will succeed + } + // For Int32, we cache a range of common values, e.g. [-1,4). + else if (typeof(TResult) == typeof(Int32)) + { + // Compare to constants to avoid static field access if outside of cached range. + // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the + // lower side, due to positive values being more common than negative as return values. + Int32 value = (Int32)(object)result; + if (value < AsyncTaskCache.EXCLUSIVE_INT32_MAX && + value >= AsyncTaskCache.INCLUSIVE_INT32_MIN) + { + Task<Int32> task = AsyncTaskCache.Int32Tasks[value - AsyncTaskCache.INCLUSIVE_INT32_MIN]; + return JitHelpers.UnsafeCast<Task<TResult>>(task); // UnsafeCast avoids a type check we know will succeed + } + } + // For other known value types, we only special-case 0 / default(TResult). + else if ( + (typeof(TResult) == typeof(UInt32) && default(UInt32) == (UInt32)(object)result) || + (typeof(TResult) == typeof(Byte) && default(Byte) == (Byte)(object)result) || + (typeof(TResult) == typeof(SByte) && default(SByte) == (SByte)(object)result) || + (typeof(TResult) == typeof(Char) && default(Char) == (Char)(object)result) || + (typeof(TResult) == typeof(Decimal) && default(Decimal) == (Decimal)(object)result) || + (typeof(TResult) == typeof(Int64) && default(Int64) == (Int64)(object)result) || + (typeof(TResult) == typeof(UInt64) && default(UInt64) == (UInt64)(object)result) || + (typeof(TResult) == typeof(Int16) && default(Int16) == (Int16)(object)result) || + (typeof(TResult) == typeof(UInt16) && default(UInt16) == (UInt16)(object)result) || + (typeof(TResult) == typeof(IntPtr) && default(IntPtr) == (IntPtr)(object)result) || + (typeof(TResult) == typeof(UIntPtr) && default(UIntPtr) == (UIntPtr)(object)result)) + { + return s_defaultResultTask; + } + } + else if (result == null) // optimized away for value types + { + return s_defaultResultTask; + } + + // No cached task is available. Manufacture a new one for this result. + return new Task<TResult>(result); + } + } + + /// <summary>Provides a cache of closed generic tasks for async methods.</summary> + internal static class AsyncTaskCache + { + // All static members are initialized inline to ensure type is beforefieldinit + + /// <summary>A cached Task{Boolean}.Result == true.</summary> + internal readonly static Task<Boolean> TrueTask = CreateCacheableTask(true); + /// <summary>A cached Task{Boolean}.Result == false.</summary> + internal readonly static Task<Boolean> FalseTask = CreateCacheableTask(false); + + /// <summary>The cache of Task{Int32}.</summary> + internal readonly static Task<Int32>[] Int32Tasks = CreateInt32Tasks(); + /// <summary>The minimum value, inclusive, for which we want a cached task.</summary> + internal const Int32 INCLUSIVE_INT32_MIN = -1; + /// <summary>The maximum value, exclusive, for which we want a cached task.</summary> + internal const Int32 EXCLUSIVE_INT32_MAX = 9; + /// <summary>Creates an array of cached tasks for the values in the range [INCLUSIVE_MIN,EXCLUSIVE_MAX).</summary> + private static Task<Int32>[] CreateInt32Tasks() + { + Contract.Assert(EXCLUSIVE_INT32_MAX >= INCLUSIVE_INT32_MIN, "Expected max to be at least min"); + var tasks = new Task<Int32>[EXCLUSIVE_INT32_MAX - INCLUSIVE_INT32_MIN]; + for (int i = 0; i < tasks.Length; i++) + { + tasks[i] = CreateCacheableTask(i + INCLUSIVE_INT32_MIN); + } + return tasks; + } + + /// <summary>Creates a non-disposable task.</summary> + /// <typeparam name="TResult">Specifies the result type.</typeparam> + /// <param name="result">The result for the task.</param> + /// <returns>The cacheable task.</returns> + internal static Task<TResult> CreateCacheableTask<TResult>(TResult result) + { + return new Task<TResult>(false, result, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); + } + } + + /// <summary>Holds state related to the builder's IAsyncStateMachine.</summary> + /// <remarks>This is a mutable struct. Be very delicate with it.</remarks> + internal struct AsyncMethodBuilderCore + { + /// <summary>A reference to the heap-allocated state machine object associated with this builder.</summary> + internal IAsyncStateMachine m_stateMachine; + /// <summary>A cached Action delegate used when dealing with a default ExecutionContext.</summary> + internal Action m_defaultContextAction; + + // This method is copy&pasted into the public Start methods to avoid size overhead of valuetype generic instantiations. + // Ideally, we would build intrinsics to get the raw ref address and raw code address of MoveNext, and just use the shared implementation. +#if false + /// <summary>Initiates the builder's execution with the associated state machine.</summary> + /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> + /// <param name="stateMachine">The state machine instance, passed by reference.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument is null (Nothing in Visual Basic).</exception> + [SecuritySafeCritical] + [DebuggerStepThrough] + internal static void Start<TStateMachine>(ref TStateMachine stateMachine) + where TStateMachine : IAsyncStateMachine + { + if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + Contract.EndContractBlock(); + + // Run the MoveNext method within a copy-on-write ExecutionContext scope. + // This allows us to undo any ExecutionContext changes made in MoveNext, + // so that they won't "leak" out of the first await. + + Thread currentThread = Thread.CurrentThread; + ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher); + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs); + stateMachine.MoveNext(); + } + finally + { + ecs.Undo(currentThread); + } + } +#endif + + /// <summary>Associates the builder with the state machine it represents.</summary> + /// <param name="stateMachine">The heap-allocated state machine object.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception> + public void SetStateMachine(IAsyncStateMachine stateMachine) + { + if (stateMachine == null) throw new ArgumentNullException("stateMachine"); + Contract.EndContractBlock(); + if (m_stateMachine != null) throw new InvalidOperationException(Environment.GetResourceString("AsyncMethodBuilder_InstanceNotInitialized")); + m_stateMachine = stateMachine; + } + + /// <summary> + /// Gets the Action to use with an awaiter's OnCompleted or UnsafeOnCompleted method. + /// On first invocation, the supplied state machine will be boxed. + /// </summary> + /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam> + /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam> + /// <param name="builder">The builder.</param> + /// <param name="stateMachine">The state machine.</param> + /// <returns>An Action to provide to the awaiter.</returns> + [SecuritySafeCritical] + internal Action GetCompletionAction(Task taskForTracing, ref MoveNextRunner runnerToInitialize) + { + Contract.Assert(m_defaultContextAction == null || m_stateMachine != null, + "Expected non-null m_stateMachine on non-null m_defaultContextAction"); + + // Alert a listening debugger that we can't make forward progress unless it slips threads. + // If we don't do this, and a method that uses "await foo;" is invoked through funceval, + // we could end up hooking up a callback to push forward the async method's state machine, + // the debugger would then abort the funceval after it takes too long, and then continuing + // execution could result in another callback being hooked up. At that point we have + // multiple callbacks registered to push the state machine, which could result in bad behavior. + Debugger.NotifyOfCrossThreadDependency(); + + // The builder needs to flow ExecutionContext, so capture it. + var capturedContext = ExecutionContext.FastCapture(); // ok to use FastCapture as we haven't made any permission demands/asserts + + // If the ExecutionContext is the default context, try to use a cached delegate, creating one if necessary. + Action action; + MoveNextRunner runner; + if (capturedContext != null && capturedContext.IsPreAllocatedDefault) + { + // Get the cached delegate, and if it's non-null, return it. + action = m_defaultContextAction; + if (action != null) + { + Contract.Assert(m_stateMachine != null, "If the delegate was set, the state machine should have been as well."); + return action; + } + + // There wasn't a cached delegate, so create one and cache it. + // The delegate won't be usable until we set the MoveNextRunner's target state machine. + runner = new MoveNextRunner(m_stateMachine); + + action = new Action(runner.RunWithDefaultContext); + if (taskForTracing != null) + { + action = OutputAsyncCausalityEvents(taskForTracing, action); + } + m_defaultContextAction = action; + } + // Otherwise, create an Action that flows this context. The context may be null. + // The delegate won't be usable until we set the MoveNextRunner's target state machine. + else + { + var runnerWithContext = new MoveNextRunnerWithContext(capturedContext, m_stateMachine); + runner = runnerWithContext; + action = new Action(runnerWithContext.RunWithCapturedContext); + + if (taskForTracing != null) + { + action = OutputAsyncCausalityEvents(taskForTracing, action); + } + + // NOTE: If capturedContext is null, we could create the Action to point directly + // to m_stateMachine.MoveNext. However, that follows a much more expensive + // delegate creation path. + } + + if (m_stateMachine == null) + runnerToInitialize = runner; + + return action; + } + + private Action OutputAsyncCausalityEvents(Task innerTask, Action continuation) + { + return CreateContinuationWrapper(continuation, () => + { + AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, innerTask.Id, CausalitySynchronousWork.Execution); + + // Invoke the original continuation + continuation.Invoke(); + + AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution); + }, innerTask); + } + + internal void PostBoxInitialization(IAsyncStateMachine stateMachine, MoveNextRunner runner, Task builtTask) + { + if (builtTask != null) + { + if (AsyncCausalityTracer.LoggingOn) + AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, builtTask.Id, "Async: " + stateMachine.GetType().Name, 0); + + if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) + System.Threading.Tasks.Task.AddToActiveTasks(builtTask); + } + + m_stateMachine = stateMachine; + m_stateMachine.SetStateMachine(m_stateMachine); + + Contract.Assert(runner.m_stateMachine == null, "The runner's state machine should not yet have been populated."); + Contract.Assert(m_stateMachine != null, "The builder's state machine field should have been initialized."); + + // Now that we have the state machine, store it into the runner that the action delegate points to. + // And return the action. + runner.m_stateMachine = m_stateMachine; // only after this line is the Action delegate usable + } + + /// <summary>Throws the exception on the ThreadPool.</summary> + /// <param name="exception">The exception to propagate.</param> + /// <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param> + internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext) + { + // Capture the exception into an ExceptionDispatchInfo so that its + // stack trace and Watson bucket info will be preserved + var edi = ExceptionDispatchInfo.Capture(exception); + + // If the user supplied a SynchronizationContext... + if (targetContext != null) + { + try + { + // Post the throwing of the exception to that context, and return. + targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi); + return; + } + catch (Exception postException) + { + // If something goes horribly wrong in the Post, we'll + // propagate both exceptions on the ThreadPool + edi = ExceptionDispatchInfo.Capture(new AggregateException(exception, postException)); + } + } + + // If we have the new error reporting APIs, report this error. Otherwise, Propagate the exception(s) on the ThreadPool +#if FEATURE_COMINTEROP + if (!WindowsRuntimeMarshal.ReportUnhandledError(edi.SourceException)) +#endif // FEATURE_COMINTEROP + { + ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi); + } + } + + /// <summary>Provides the ability to invoke a state machine's MoveNext method under a supplied ExecutionContext.</summary> + internal sealed class MoveNextRunnerWithContext : MoveNextRunner + { + /// <summary>The context with which to run MoveNext.</summary> + private readonly ExecutionContext m_context; + + /// <summary>Initializes the runner.</summary> + /// <param name="context">The context with which to run MoveNext.</param> + [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC + internal MoveNextRunnerWithContext(ExecutionContext context, IAsyncStateMachine stateMachine) : base(stateMachine) + { + m_context = context; + } + + /// <summary>Invokes MoveNext under the provided context.</summary> + [SecuritySafeCritical] + internal void RunWithCapturedContext() + { + Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); + + if (m_context != null) + { + try + { + // Use the context and callback to invoke m_stateMachine.MoveNext. + ExecutionContext.Run(m_context, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true); + } + finally { m_context.Dispose(); } + } + else + { + m_stateMachine.MoveNext(); + } + } + } + + /// <summary>Provides the ability to invoke a state machine's MoveNext method.</summary> + internal class MoveNextRunner + { + /// <summary>The state machine whose MoveNext method should be invoked.</summary> + internal IAsyncStateMachine m_stateMachine; + + /// <summary>Initializes the runner.</summary> + [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC + internal MoveNextRunner(IAsyncStateMachine stateMachine) + { + m_stateMachine = stateMachine; + } + + /// <summary>Invokes MoveNext under the default context.</summary> + [SecuritySafeCritical] + internal void RunWithDefaultContext() + { + Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run."); + ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true); + } + + /// <summary>Gets a delegate to the InvokeMoveNext method.</summary> + protected static ContextCallback InvokeMoveNextCallback + { + [SecuritySafeCritical] + get { return s_invokeMoveNext ?? (s_invokeMoveNext = InvokeMoveNext); } + } + + /// <summary>Cached delegate used with ExecutionContext.Run.</summary> + [SecurityCritical] + private static ContextCallback s_invokeMoveNext; // lazily-initialized due to SecurityCritical attribution + + /// <summary>Invokes the MoveNext method on the supplied IAsyncStateMachine.</summary> + /// <param name="stateMachine">The IAsyncStateMachine machine instance.</param> + [SecurityCritical] // necessary for ContextCallback in CoreCLR + private static void InvokeMoveNext(object stateMachine) + { + ((IAsyncStateMachine)stateMachine).MoveNext(); + } + } + + /// <summary> + /// Logically we pass just an Action (delegate) to a task for its action to 'ContinueWith' when it completes. + /// However debuggers and profilers need more information about what that action is. (In particular what + /// the action after that is and after that. To solve this problem we create a 'ContinuationWrapper + /// which when invoked just does the original action (the invoke action), but also remembers other information + /// (like the action after that (which is also a ContinuationWrapper and thus form a linked list). + // We also store that task if the action is associate with at task. + /// </summary> + private class ContinuationWrapper + { + internal readonly Action m_continuation; // This is continuation which will happen after m_invokeAction (and is probably a ContinuationWrapper) + private readonly Action m_invokeAction; // This wrapper is an action that wraps another action, this is that Action. + internal readonly Task m_innerTask; // If the continuation is logically going to invoke a task, this is that task (may be null) + + internal ContinuationWrapper(Action continuation, Action invokeAction, Task innerTask) + { + Contract.Requires(continuation != null, "Expected non-null continuation"); + + // If we don't have a task, see if our continuation is a wrapper and use that. + if (innerTask == null) + innerTask = TryGetContinuationTask(continuation); + + m_continuation = continuation; + m_innerTask = innerTask; + m_invokeAction = invokeAction; + } + + internal void Invoke() + { + m_invokeAction(); + } + } + + internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask = null) + { + return new ContinuationWrapper(continuation, invokeAction, innerTask).Invoke; + } + + internal static Action TryGetStateMachineForDebugger(Action action) + { + object target = action.Target; + var runner = target as AsyncMethodBuilderCore.MoveNextRunner; + if (runner != null) + { + return new Action(runner.m_stateMachine.MoveNext); + } + + var continuationWrapper = target as ContinuationWrapper; + if (continuationWrapper != null) + { + return TryGetStateMachineForDebugger(continuationWrapper.m_continuation); + } + + return action; + } + + ///<summary> + /// Given an action, see if it is a contiunation wrapper and has a Task associated with it. If so return it (null otherwise) + ///</summary> + internal static Task TryGetContinuationTask(Action action) + { + if (action != null) + { + var asWrapper = action.Target as ContinuationWrapper; + if (asWrapper != null) + return asWrapper.m_innerTask; + } + return null; + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs new file mode 100644 index 0000000000..f1fc9ced82 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + public sealed class AsyncStateMachineAttribute : StateMachineAttribute + { + public AsyncStateMachineAttribute(Type stateMachineType) + : base(stateMachineType) + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs new file mode 100644 index 0000000000..330934cf95 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + public sealed class CallerFilePathAttribute : Attribute + { + public CallerFilePathAttribute() + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs new file mode 100644 index 0000000000..9c87e8e25f --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + public sealed class CallerLineNumberAttribute : Attribute + { + public CallerLineNumberAttribute() + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs new file mode 100644 index 0000000000..4fc70908fb --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + public sealed class CallerMemberNameAttribute : Attribute + { + public CallerMemberNameAttribute() + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs new file mode 100644 index 0000000000..f44251d480 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.CompilerServices +{ + // Types used in Custom Modifier to specify calling conventions. + [System.Runtime.InteropServices.ComVisible(true)] + public class CallConvCdecl + { + } + + [System.Runtime.InteropServices.ComVisible(true)] + public class CallConvStdcall + { + } + + [System.Runtime.InteropServices.ComVisible(true)] + public class CallConvThiscall + { + } + + [System.Runtime.InteropServices.ComVisible(true)] + public class CallConvFastcall + { + } + +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs new file mode 100644 index 0000000000..5e4f19410b --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +namespace System.Runtime.CompilerServices +{ + + using System; + + /// IMPORTANT: Keep this in sync with corhdr.h +[Serializable] +[Flags] +[System.Runtime.InteropServices.ComVisible(true)] + public enum CompilationRelaxations : int + { + NoStringInterning = 0x0008, // Start in 0x0008, we had other non public flags in this enum before, + // so we'll start here just in case somebody used them. This flag is only + // valid when set for Assemblies. + }; + +[Serializable] +[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Method)] +[System.Runtime.InteropServices.ComVisible(true)] + public class CompilationRelaxationsAttribute : Attribute + { + private int m_relaxations; // The relaxations. + + public CompilationRelaxationsAttribute ( + int relaxations) + { + m_relaxations = relaxations; + } + + public CompilationRelaxationsAttribute ( + CompilationRelaxations relaxations) + { + m_relaxations = (int) relaxations; + } + + public int CompilationRelaxations + { + get + { + return m_relaxations; + } + } + } + +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs new file mode 100644 index 0000000000..1778506c7c --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.CompilerServices { + +[Serializable] +[AttributeUsage(AttributeTargets.All, Inherited = true)] + public sealed class CompilerGeneratedAttribute : Attribute + { + public CompilerGeneratedAttribute () {} + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs new file mode 100644 index 0000000000..65755f6baa --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** +** Purpose: Attribute used to communicate to the VS7 debugger +** that a class should be treated as if it has +** global scope. +** +** +===========================================================*/ + + +namespace System.Runtime.CompilerServices +{ + [Serializable] + [AttributeUsage(AttributeTargets.Class)] + [System.Runtime.InteropServices.ComVisible(true)] + public class CompilerGlobalScopeAttribute : Attribute + { + public CompilerGlobalScopeAttribute () {} + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs new file mode 100644 index 0000000000..a7b4aca480 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // The CLR data marshaler has some behaviors that are incompatible with + // C++. Specifically, C++ treats boolean variables as byte size, whereas + // the marshaller treats them as 4-byte size. Similarly, C++ treats + // wchar_t variables as 4-byte size, whereas the marshaller treats them + // as single byte size under certain conditions. In order to work around + // such issues, the C++ compiler will emit a type that the marshaller will + // marshal using the correct sizes. In addition, the compiler will place + // this modopt onto the variables to indicate that the specified type is + // not the true type. Any compiler that needed to deal with similar + // marshalling incompatibilities could use this attribute as well. + // + // Indicates that the modified instance differs from its true type for + // correct marshalling. + public static class CompilerMarshalOverride + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs new file mode 100644 index 0000000000..21d677241d --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs @@ -0,0 +1,795 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** Description: Compiler support for runtime-generated "object fields." +** +** Lets DLR and other language compilers expose the ability to +** attach arbitrary "properties" to instanced managed objects at runtime. +** +** We expose this support as a dictionary whose keys are the +** instanced objects and the values are the "properties." +** +** Unlike a regular dictionary, ConditionalWeakTables will not +** keep keys alive. +** +** +** Lifetimes of keys and values: +** +** Inserting a key and value into the dictonary will not +** prevent the key from dying, even if the key is strongly reachable +** from the value. +** +** Prior to ConditionalWeakTable, the CLR did not expose +** the functionality needed to implement this guarantee. +** +** Once the key dies, the dictionary automatically removes +** the key/value entry. +** +** +** Relationship between ConditionalWeakTable and Dictionary: +** +** ConditionalWeakTable mirrors the form and functionality +** of the IDictionary interface for the sake of api consistency. +** +** Unlike Dictionary, ConditionalWeakTable is fully thread-safe +** and requires no additional locking to be done by callers. +** +** ConditionalWeakTable defines equality as Object.ReferenceEquals(). +** ConditionalWeakTable does not invoke GetHashCode() overrides. +** +** It is not intended to be a general purpose collection +** and it does not formally implement IDictionary or +** expose the full public surface area. +** +** +** +** Thread safety guarantees: +** +** ConditionalWeakTable is fully thread-safe and requires no +** additional locking to be done by callers. +** +** +** OOM guarantees: +** +** Will not corrupt unmanaged handle table on OOM. No guarantees +** about managed weak table consistency. Native handles reclamation +** may be delayed until appdomain shutdown. +===========================================================*/ + +namespace System.Runtime.CompilerServices +{ + using System; + using System.Collections.Generic; + using System.Runtime.Versioning; + using System.Runtime.InteropServices; + + + #region ConditionalWeakTable + [System.Runtime.InteropServices.ComVisible(false)] + public sealed class ConditionalWeakTable<TKey, TValue> + where TKey : class + where TValue : class + { + + #region Constructors + [System.Security.SecuritySafeCritical] + public ConditionalWeakTable() + { + _buckets = Array.Empty<int>(); + _entries = Array.Empty<Entry>(); + _freeList = -1; + _lock = new Object(); + + Resize(); // Resize at once (so won't need "if initialized" checks all over) + } + #endregion + + #region Public Members + //-------------------------------------------------------------------------------------------- + // key: key of the value to find. Cannot be null. + // value: if the key is found, contains the value associated with the key upon method return. + // if the key is not found, contains default(TValue). + // + // Method returns "true" if key was found, "false" otherwise. + // + // Note: The key may get garbaged collected during the TryGetValue operation. If so, TryGetValue + // may at its discretion, return "false" and set "value" to the default (as if the key was not present.) + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + public bool TryGetValue(TKey key, out TValue value) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + lock(_lock) + { + VerifyIntegrity(); + return TryGetValueWorker(key, out value); + } + } + + //-------------------------------------------------------------------------------------------- + // key: key to add. May not be null. + // value: value to associate with key. + // + // If the key is already entered into the dictionary, this method throws an exception. + // + // Note: The key may get garbage collected during the Add() operation. If so, Add() + // has the right to consider any prior entries successfully removed and add a new entry without + // throwing an exception. + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + public void Add(TKey key, TValue value) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + lock(_lock) + { + VerifyIntegrity(); + _invalid = true; + + int entryIndex = FindEntry(key); + if (entryIndex != -1) + { + _invalid = false; + ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); + } + + CreateEntry(key, value); + _invalid = false; + } + + } + + //-------------------------------------------------------------------------------------------- + // key: key to remove. May not be null. + // + // Returns true if the key is found and removed. Returns false if the key was not in the dictionary. + // + // Note: The key may get garbage collected during the Remove() operation. If so, + // Remove() will not fail or throw, however, the return value can be either true or false + // depending on the race condition. + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + public bool Remove(TKey key) + { + if (key == null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + } + + lock(_lock) + { + VerifyIntegrity(); + _invalid = true; + + int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; + int bucket = hashCode % _buckets.Length; + int last = -1; + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + { + if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key) + { + if (last == -1) + { + _buckets[bucket] = _entries[entriesIndex].next; + } + else + { + _entries[last].next = _entries[entriesIndex].next; + } + + _entries[entriesIndex].depHnd.Free(); + _entries[entriesIndex].next = _freeList; + + _freeList = entriesIndex; + + _invalid = false; + return true; + + } + last = entriesIndex; + } + _invalid = false; + return false; + } + } + + + //-------------------------------------------------------------------------------------------- + // key: key of the value to find. Cannot be null. + // createValueCallback: callback that creates value for key. Cannot be null. + // + // Atomically tests if key exists in table. If so, returns corresponding value. If not, + // invokes createValueCallback() passing it the key. The returned value is bound to the key in the table + // and returned as the result of GetValue(). + // + // If multiple threads try to initialize the same key, the table may invoke createValueCallback + // multiple times with the same key. Exactly one of these calls will succeed and the returned + // value of that call will be the one added to the table and returned by all the racing GetValue() calls. + // + // This rule permits the table to invoke createValueCallback outside the internal table lock + // to prevent deadlocks. + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + public TValue GetValue(TKey key, CreateValueCallback createValueCallback) + { + // Our call to TryGetValue() validates key so no need for us to. + // + // if (key == null) + // { + // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); + // } + + if (createValueCallback == null) + { + throw new ArgumentNullException("createValueCallback"); + } + + TValue existingValue; + if (TryGetValue(key, out existingValue)) + { + return existingValue; + } + + // If we got here, the key is not currently in table. Invoke the callback (outside the lock) + // to generate the new value for the key. + TValue newValue = createValueCallback(key); + + lock(_lock) + { + VerifyIntegrity(); + _invalid = true; + + // Now that we've retaken the lock, must recheck in case there was a race condition to add the key. + if (TryGetValueWorker(key, out existingValue)) + { + _invalid = false; + return existingValue; + } + else + { + CreateEntry(key, newValue); + _invalid = false; + return newValue; + } + } + } + + //-------------------------------------------------------------------------------------------- + // key: key of the value to find. Cannot be null. + // + // Helper method to call GetValue without passing a creation delegate. Uses Activator.CreateInstance + // to create new instances as needed. If TValue does not have a default constructor, this will + // throw. + //-------------------------------------------------------------------------------------------- + public TValue GetOrCreateValue(TKey key) + { + return GetValue(key, k => Activator.CreateInstance<TValue>()); + } + + public delegate TValue CreateValueCallback(TKey key); + + #endregion + + #region internal members + + //-------------------------------------------------------------------------------------------- + // Find a key that equals (value equality) with the given key - don't use in perf critical path + // Note that it calls out to Object.Equals which may calls the override version of Equals + // and that may take locks and leads to deadlock + // Currently it is only used by WinRT event code and you should only use this function + // if you know for sure that either you won't run into dead locks or you need to live with the + // possiblity + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + [FriendAccessAllowed] + internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value) + { + lock (_lock) + { + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + { + object thisKey, thisValue; + _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out thisKey, out thisValue); + if (Object.Equals(thisKey, key)) + { + value = (TValue) thisValue; + return (TKey) thisKey; + } + } + } + } + + value = default(TValue); + return null; + } + + //-------------------------------------------------------------------------------------------- + // Returns a collection of keys - don't use in perf critical path + //-------------------------------------------------------------------------------------------- + internal ICollection<TKey> Keys + { + [System.Security.SecuritySafeCritical] + get + { + List<TKey> list = new List<TKey>(); + lock (_lock) + { + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + { + TKey thisKey = (TKey) _entries[entriesIndex].depHnd.GetPrimary(); + if (thisKey != null) + { + list.Add(thisKey); + } + } + } + } + + return list; + } + } + + //-------------------------------------------------------------------------------------------- + // Returns a collection of values - don't use in perf critical path + //-------------------------------------------------------------------------------------------- + internal ICollection<TValue> Values + { + [System.Security.SecuritySafeCritical] + get + { + List<TValue> list = new List<TValue>(); + lock (_lock) + { + for (int bucket = 0; bucket < _buckets.Length; ++bucket) + { + for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + { + Object primary = null; + Object secondary = null; + + _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); + + // Now that we've secured a strong reference to the secondary, must check the primary again + // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an + // expired key as a live key with a null value.) + if (primary != null) + { + list.Add((TValue)secondary); + } + } + } + } + + return list; + } + } + + //-------------------------------------------------------------------------------------------- + // Clear all the key/value pairs + //-------------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + internal void Clear() + { + lock (_lock) + { + // Clear the buckets + for (int bucketIndex = 0; bucketIndex < _buckets.Length; bucketIndex++) + { + _buckets[bucketIndex] = -1; + } + + // Clear the entries and link them backwards together as part of free list + int entriesIndex; + for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + { + if (_entries[entriesIndex].depHnd.IsAllocated) + { + _entries[entriesIndex].depHnd.Free(); + } + + // Link back wards as free list + _entries[entriesIndex].next = entriesIndex - 1; + } + + _freeList = entriesIndex - 1; + } + } + + #endregion + + #region Private Members + [System.Security.SecurityCritical] + //---------------------------------------------------------------------------------------- + // Worker for finding a key/value pair + // + // Preconditions: + // Must hold _lock. + // Key already validated as non-null + //---------------------------------------------------------------------------------------- + private bool TryGetValueWorker(TKey key, out TValue value) + { + int entryIndex = FindEntry(key); + if (entryIndex != -1) + { + Object primary = null; + Object secondary = null; + _entries[entryIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary); + // Now that we've secured a strong reference to the secondary, must check the primary again + // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an + // expired key as a live key with a null value.) + if (primary != null) + { + value = (TValue)secondary; + return true; + } + } + + value = default(TValue); + return false; + } + + //---------------------------------------------------------------------------------------- + // Worker for adding a new key/value pair. + // + // Preconditions: + // Must hold _lock. + // Key already validated as non-null and not already in table. + //---------------------------------------------------------------------------------------- + [System.Security.SecurityCritical] + private void CreateEntry(TKey key, TValue value) + { + if (_freeList == -1) + { + Resize(); + } + + int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; + int bucket = hashCode % _buckets.Length; + + int newEntry = _freeList; + _freeList = _entries[newEntry].next; + + _entries[newEntry].hashCode = hashCode; + _entries[newEntry].depHnd = new DependentHandle(key, value); + _entries[newEntry].next = _buckets[bucket]; + + _buckets[bucket] = newEntry; + + } + + //---------------------------------------------------------------------------------------- + // This does two things: resize and scrub expired keys off bucket lists. + // + // Precondition: + // Must hold _lock. + // + // Postcondition: + // _freeList is non-empty on exit. + //---------------------------------------------------------------------------------------- + [System.Security.SecurityCritical] + private void Resize() + { + // Start by assuming we won't resize. + int newSize = _buckets.Length; + + // If any expired keys exist, we won't resize. + bool hasExpiredEntries = false; + int entriesIndex; + for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + { + if ( _entries[entriesIndex].depHnd.IsAllocated && _entries[entriesIndex].depHnd.GetPrimary() == null) + { + hasExpiredEntries = true; + break; + } + } + + if (!hasExpiredEntries) + { + newSize = System.Collections.HashHelpers.GetPrime(_buckets.Length == 0 ? _initialCapacity + 1 : _buckets.Length * 2); + } + + + // Reallocate both buckets and entries and rebuild the bucket and freelists from scratch. + // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket. + int newFreeList = -1; + int[] newBuckets = new int[newSize]; + for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++) + { + newBuckets[bucketIndex] = -1; + } + Entry[] newEntries = new Entry[newSize]; + + // Migrate existing entries to the new table. + for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++) + { + DependentHandle depHnd = _entries[entriesIndex].depHnd; + if (depHnd.IsAllocated && depHnd.GetPrimary() != null) + { + // Entry is used and has not expired. Link it into the appropriate bucket list. + int bucket = _entries[entriesIndex].hashCode % newSize; + newEntries[entriesIndex].depHnd = depHnd; + newEntries[entriesIndex].hashCode = _entries[entriesIndex].hashCode; + newEntries[entriesIndex].next = newBuckets[bucket]; + newBuckets[bucket] = entriesIndex; + } + else + { + // Entry has either expired or was on the freelist to begin with. Either way + // insert it on the new freelist. + _entries[entriesIndex].depHnd.Free(); + newEntries[entriesIndex].depHnd = new DependentHandle(); + newEntries[entriesIndex].next = newFreeList; + newFreeList = entriesIndex; + } + } + + // Add remaining entries to freelist. + while (entriesIndex != newEntries.Length) + { + newEntries[entriesIndex].depHnd = new DependentHandle(); + newEntries[entriesIndex].next = newFreeList; + newFreeList = entriesIndex; + entriesIndex++; + } + + _buckets = newBuckets; + _entries = newEntries; + _freeList = newFreeList; + } + + //---------------------------------------------------------------------------------------- + // Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found.") + // + // Preconditions: + // Must hold _lock. + // Key already validated as non-null. + //---------------------------------------------------------------------------------------- + [System.Security.SecurityCritical] + private int FindEntry(TKey key) + { + int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue; + for (int entriesIndex = _buckets[hashCode % _buckets.Length]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next) + { + if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key) + { + return entriesIndex; + } + } + return -1; + } + + //---------------------------------------------------------------------------------------- + // Precondition: + // Must hold _lock. + //---------------------------------------------------------------------------------------- + private void VerifyIntegrity() + { + if (_invalid) + { + throw new InvalidOperationException(Environment.GetResourceString("CollectionCorrupted")); + } + } + + //---------------------------------------------------------------------------------------- + // Finalizer. + //---------------------------------------------------------------------------------------- + [System.Security.SecuritySafeCritical] + ~ConditionalWeakTable() + { + + // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD, + // don't bother. + // + // (Despite its name, Environment.HasShutdownStart also returns true if the current AD is finalizing.) + if (Environment.HasShutdownStarted) + { + return; + } + + if (_lock != null) + { + lock(_lock) + { + if (_invalid) + { + return; + } + Entry[] entries = _entries; + + // Make sure anyone sneaking into the table post-resurrection + // gets booted before they can damage the native handle table. + _invalid = true; + _entries = null; + _buckets = null; + + for (int entriesIndex = 0; entriesIndex < entries.Length; entriesIndex++) + { + entries[entriesIndex].depHnd.Free(); + } + } + } + } + #endregion + + #region Private Data Members + //-------------------------------------------------------------------------------------------- + // Entry can be in one of three states: + // + // - Linked into the freeList (_freeList points to first entry) + // depHnd.IsAllocated == false + // hashCode == <dontcare> + // next links to next Entry on freelist) + // + // - Used with live key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry) + // depHnd.IsAllocated == true, depHnd.GetPrimary() != null + // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & Int32.MaxValue + // next links to next Entry in bucket. + // + // - Used with dead key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry) + // depHnd.IsAllocated == true, depHnd.GetPrimary() == null + // hashCode == <notcare> + // next links to next Entry in bucket. + // + // The only difference between "used with live key" and "used with dead key" is that + // depHnd.GetPrimary() returns null. The transition from "used with live key" to "used with dead key" + // happens asynchronously as a result of normal garbage collection. The dictionary itself + // receives no notification when this happens. + // + // When the dictionary grows the _entries table, it scours it for expired keys and puts those + // entries back on the freelist. + //-------------------------------------------------------------------------------------------- + private struct Entry + { + public DependentHandle depHnd; // Holds key and value using a weak reference for the key and a strong reference + // for the value that is traversed only if the key is reachable without going through the value. + public int hashCode; // Cached copy of key's hashcode + public int next; // Index of next entry, -1 if last + } + + private int[] _buckets; // _buckets[hashcode & _buckets.Length] contains index of first entry in bucket (-1 if empty) + private Entry[] _entries; + private int _freeList; // -1 = empty, else index of first unused Entry + private const int _initialCapacity = 5; + private readonly Object _lock; // this could be a ReaderWriterLock but CoreCLR does not support RWLocks. + private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock. + #endregion + } + #endregion + + + + + #region DependentHandle + //========================================================================================= + // This struct collects all operations on native DependentHandles. The DependentHandle + // merely wraps an IntPtr so this struct serves mainly as a "managed typedef." + // + // DependentHandles exist in one of two states: + // + // IsAllocated == false + // No actual handle is allocated underneath. Illegal to call GetPrimary + // or GetPrimaryAndSecondary(). Ok to call Free(). + // + // Initializing a DependentHandle using the nullary ctor creates a DependentHandle + // that's in the !IsAllocated state. + // (! Right now, we get this guarantee for free because (IntPtr)0 == NULL unmanaged handle. + // ! If that assertion ever becomes false, we'll have to add an _isAllocated field + // ! to compensate.) + // + // + // IsAllocated == true + // There's a handle allocated underneath. You must call Free() on this eventually + // or you cause a native handle table leak. + // + // This struct intentionally does no self-synchronization. It's up to the caller to + // to use DependentHandles in a thread-safe way. + //========================================================================================= + [ComVisible(false)] + struct DependentHandle + { + #region Constructors + #if FEATURE_CORECLR + [System.Security.SecuritySafeCritical] // auto-generated + #else + [System.Security.SecurityCritical] + #endif + public DependentHandle(Object primary, Object secondary) + { + IntPtr handle = (IntPtr)0; + nInitialize(primary, secondary, out handle); + // no need to check for null result: nInitialize expected to throw OOM. + _handle = handle; + } + #endregion + + #region Public Members + public bool IsAllocated + { + get + { + return _handle != (IntPtr)0; + } + } + + // Getting the secondary object is more expensive than getting the first so + // we provide a separate primary-only accessor for those times we only want the + // primary. + #if FEATURE_CORECLR + [System.Security.SecuritySafeCritical] // auto-generated + #else + [System.Security.SecurityCritical] + #endif + public Object GetPrimary() + { + Object primary; + nGetPrimary(_handle, out primary); + return primary; + } + + #if FEATURE_CORECLR + [System.Security.SecuritySafeCritical] // auto-generated + #else + [System.Security.SecurityCritical] + #endif + public void GetPrimaryAndSecondary(out Object primary, out Object secondary) + { + nGetPrimaryAndSecondary(_handle, out primary, out secondary); + } + + //---------------------------------------------------------------------- + // Forces dependentHandle back to non-allocated state (if not already there) + // and frees the handle if needed. + //---------------------------------------------------------------------- + [System.Security.SecurityCritical] + public void Free() + { + if (_handle != (IntPtr)0) + { + IntPtr handle = _handle; + _handle = (IntPtr)0; + nFree(handle); + } + } + #endregion + + #region Private Members + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void nInitialize(Object primary, Object secondary, out IntPtr dependentHandle); + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void nGetPrimary(IntPtr dependentHandle, out Object primary); + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void nGetPrimaryAndSecondary(IntPtr dependentHandle, out Object primary, out Object secondary); + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void nFree(IntPtr dependentHandle); + #endregion + + #region Private Data Member + private IntPtr _handle; + #endregion + + } // struct DependentHandle + #endregion +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs new file mode 100644 index 0000000000..c912095bda --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Collections.Generic; + +namespace System.Runtime.CompilerServices +{ + [Serializable] + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] + [System.Runtime.InteropServices.ComVisible(true)] + public abstract class CustomConstantAttribute : Attribute + { + public abstract Object Value { get; } + + internal static object GetRawConstant(CustomAttributeData attr) + { + foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments) + { + if (namedArgument.MemberInfo.Name.Equals("Value")) + return namedArgument.TypedValue.Value; + } + + // Return DBNull to indicate that no default value is available. + // Not to be confused with a null return which indicates a null default value. + return DBNull.Value; + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs new file mode 100644 index 0000000000..4362aa84a1 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using System.Diagnostics.Contracts; + +namespace System.Runtime.CompilerServices +{ + [Serializable] + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class DateTimeConstantAttribute : CustomConstantAttribute + { + public DateTimeConstantAttribute(long ticks) + { + date = new System.DateTime(ticks); + } + + public override Object Value + { + get + { + return date; + } + } + + internal static DateTime GetRawDateTimeConstant(CustomAttributeData attr) + { + Contract.Requires(attr.Constructor.DeclaringType == typeof(DateTimeConstantAttribute)); + Contract.Requires(attr.ConstructorArguments.Count == 1); + + foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments) + { + if (namedArgument.MemberInfo.Name.Equals("Value")) + { + return new DateTime((long)namedArgument.TypedValue.Value); + } + } + + // Look at the ctor argument if the "Value" property was not explicitly defined. + return new DateTime((long)attr.ConstructorArguments[0].Value); + } + + private System.DateTime date; + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs new file mode 100644 index 0000000000..39a4c86b72 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +// Note: If you add a new ctor overloads you need to update ParameterInfo.RawDefaultValue + +using System.Reflection; +using System.Diagnostics.Contracts; +using System.Collections.Generic; + +namespace System.Runtime.CompilerServices +{ + [Serializable] + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class DecimalConstantAttribute : Attribute + { + [CLSCompliant(false)] + public DecimalConstantAttribute( + byte scale, + byte sign, + uint hi, + uint mid, + uint low + ) + { + dec = new System.Decimal((int) low, (int)mid, (int)hi, (sign != 0), scale); + } + + public DecimalConstantAttribute( + byte scale, + byte sign, + int hi, + int mid, + int low + ) + { + dec = new System.Decimal(low, mid, hi, (sign != 0), scale); + } + + + public System.Decimal Value + { + get + { + return dec; + } + } + + internal static Decimal GetRawDecimalConstant(CustomAttributeData attr) + { + Contract.Requires(attr.Constructor.DeclaringType == typeof(DecimalConstantAttribute)); + + foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments) + { + if (namedArgument.MemberInfo.Name.Equals("Value")) + { + // This is not possible because Decimal cannot be represented directly in the metadata. + Contract.Assert(false, "Decimal cannot be represented directly in the metadata."); + return (Decimal)namedArgument.TypedValue.Value; + } + } + + ParameterInfo[] parameters = attr.Constructor.GetParameters(); + Contract.Assert(parameters.Length == 5); + + System.Collections.Generic.IList<CustomAttributeTypedArgument> args = attr.ConstructorArguments; + Contract.Assert(args.Count == 5); + + if (parameters[2].ParameterType == typeof(uint)) + { + // DecimalConstantAttribute(byte scale, byte sign, uint hi, uint mid, uint low) + int low = (int)(UInt32)args[4].Value; + int mid = (int)(UInt32)args[3].Value; + int hi = (int)(UInt32)args[2].Value; + byte sign = (byte)args[1].Value; + byte scale = (byte)args[0].Value; + + return new System.Decimal(low, mid, hi, (sign != 0), scale); + } + else + { + // DecimalConstantAttribute(byte scale, byte sign, int hi, int mid, int low) + int low = (int)args[4].Value; + int mid = (int)args[3].Value; + int hi = (int)args[2].Value; + byte sign = (byte)args[1].Value; + byte scale = (byte)args[0].Value; + + return new System.Decimal(low, mid, hi, (sign != 0), scale); + } + } + + private System.Decimal dec; + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs new file mode 100644 index 0000000000..75558d4e7e --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.All), + ComVisible(false)] + internal sealed class DecoratedNameAttribute : Attribute + { + public DecoratedNameAttribute(string decoratedName) + {} + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs new file mode 100644 index 0000000000..46dae10fdd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace System.Runtime.CompilerServices +{ + using System; + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)] + public sealed class DisablePrivateReflectionAttribute : Attribute + { + public DisablePrivateReflectionAttribute() {} + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs new file mode 100644 index 0000000000..303151f576 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.CompilerServices { + + using System; + + // Custom attribute to indicating a TypeDef is a discardable attribute +[System.Runtime.InteropServices.ComVisible(true)] + public class DiscardableAttribute : Attribute + { + public DiscardableAttribute() + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs new file mode 100644 index 0000000000..6ec8fa04f5 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; + +namespace System.Runtime.CompilerServices +{ + /// <summary> + /// Indicates that a method is an extension method, or that a class or assembly contains extension methods. + /// </summary> + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] + public sealed class ExtensionAttribute : Attribute { } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs new file mode 100644 index 0000000000..679e304ad1 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + using System; + +[Serializable] +[AttributeUsage(AttributeTargets.Field)] + sealed public class FixedAddressValueTypeAttribute : Attribute + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs new file mode 100644 index 0000000000..a7d01b12c4 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** Purpose: Used by a compiler for generating value types +** in-place within other value types containing a certain +** number of elements of the given (primitive) type. Somewhat +** similar to P/Invoke's ByValTStr attribute. +** Used by C# with this syntax: "fixed int buffer[10];" +** +===========================================================*/ +using System; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Field, Inherited=false)] + public sealed class FixedBufferAttribute : Attribute + { + private Type elementType; + private int length; + + public FixedBufferAttribute(Type elementType, int length) + { + this.elementType = elementType; + this.length = length; + } + + public Type ElementType { + get { + return elementType; + } + } + + public int Length { + get { + return length; + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs new file mode 100644 index 0000000000..aee3bc2230 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Class: FormattableStringFactory +** +** +** Purpose: implementation of the FormattableStringFactory +** class. +** +===========================================================*/ +namespace System.Runtime.CompilerServices +{ + /// <summary> + /// A factory type used by compilers to create instances of the type <see cref="FormattableString"/>. + /// </summary> + public static class FormattableStringFactory + { + /// <summary> + /// Create a <see cref="FormattableString"/> from a composite format string and object + /// array containing zero or more objects to format. + /// </summary> + public static FormattableString Create(string format, params object[] arguments) + { + if (format == null) + { + throw new ArgumentNullException("format"); + } + + if (arguments == null) + { + throw new ArgumentNullException("arguments"); + } + + return new ConcreteFormattableString(format, arguments); + } + + private sealed class ConcreteFormattableString : FormattableString + { + private readonly string _format; + private readonly object[] _arguments; + + internal ConcreteFormattableString(string format, object[] arguments) + { + _format = format; + _arguments = arguments; + } + + public override string Format { get { return _format; } } + public override object[] GetArguments() { return _arguments; } + public override int ArgumentCount { get { return _arguments.Length; } } + public override object GetArgument(int index) { return _arguments[index]; } + public override string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, _format, _arguments); } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs new file mode 100644 index 0000000000..944a2868f2 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ +[Serializable] +[AttributeUsage(AttributeTargets.Struct)] + public sealed class HasCopySemanticsAttribute : Attribute + { + public HasCopySemanticsAttribute() + {} + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs new file mode 100644 index 0000000000..7fb7ea5395 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// +// +// +// Represents state machines generated for asynchronous methods. +// +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +namespace System.Runtime.CompilerServices +{ + /// <summary> + /// Represents state machines generated for asynchronous methods. + /// This type is intended for compiler use only. + /// </summary> + public interface IAsyncStateMachine + { + /// <summary>Moves the state machine to its next state.</summary> + void MoveNext(); + /// <summary>Configures the state machine with a heap-allocated replica.</summary> + /// <param name="stateMachine">The heap-allocated replica.</param> + void SetStateMachine(IAsyncStateMachine stateMachine); + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs new file mode 100644 index 0000000000..7ba9434575 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +// +// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the +// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its +// interface map. +// + +using System; + +namespace System.Runtime.CompilerServices +{ + public interface ICastable + { + // This is called if casting this object to the given interface type would otherwise fail. Casting + // here means the IL isinst and castclass instructions in the case where they are given an interface + // type as the target type. + // + // A return value of true indicates the cast is valid. + // + // If false is returned when this is called as part of a castclass then the usual InvalidCastException + // will be thrown unless an alternate exception is assigned to the castError output parameter. This + // parameter is ignored on successful casts or during the evaluation of an isinst (which returns null + // rather than throwing on error). + // + // No exception should be thrown from this method (it will cause unpredictable effects, including the + // possibility of an immediate failfast). + // + // The results of this call are not cached, so it is advisable to provide a performant implementation. + // + // The results of this call should be invariant for the same class, interface type pair. That is + // because this is the only guard placed before an interface invocation at runtime. If a type decides + // it no longer wants to implement a given interface it has no way to synchronize with callers that + // have already cached this relationship and can invoke directly via the interface pointer. + bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError); + + // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find + // the given interface type in the interface map of this object. + // + // It allows the implementor to return an alternate class type which does implement the interface. The + // interface lookup shall be performed again on this type (failure to find the interface this time + // resulting in a fail fast) and the corresponding implemented method on that class called instead. + // + // Naturally, since the call is dispatched to a method on a class which does not match the type of the + // this pointer, extreme care must be taken in the implementation of the interface methods of this + // surrogate type. + // + // No exception should be thrown from this method (it will cause unpredictable effects, including the + // possibility of an immediate failfast). + // + // There is no error path defined here. By construction all interface dispatches will already have + // been verified via the castclass/isinst mechanism (and thus a call to IsInstanceOfInterface above) + // so this method is expected to succeed in all cases. The contract for interface dispatch does not + // include any errors from the infrastructure, of which this is a part. + // + // The results of this lookup are cached so computation of the result is not as perf-sensitive as + // IsInstanceOfInterface. + RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType); + } + + /// <summary> + /// Helpers that allows VM to call into ICastable methods without having to deal with RuntimeTypeHandle. + /// RuntimeTypeHandle is a struct and is always passed in stack in x86, which our VM call helpers don't + /// particularly like. + /// </summary> + class ICastableHelpers + { + internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, out Exception castError) + { + return castable.IsInstanceOfInterface(new RuntimeTypeHandle(type), out castError); + } + + internal static RuntimeType GetImplType(ICastable castable, RuntimeType interfaceType) + { + return castable.GetImplType(new RuntimeTypeHandle(interfaceType)).GetRuntimeType(); + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs new file mode 100644 index 0000000000..d6dfcbbbb9 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices +{ +[Serializable] +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class IDispatchConstantAttribute : CustomConstantAttribute + { + public IDispatchConstantAttribute() + { + } + + public override Object Value + { + get + { + return new DispatchWrapper(null); + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs new file mode 100644 index 0000000000..872a79b72b --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= +// +// +// +// Interfaces used to represent instances that notify listeners of their completion via continuations. +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +using System; +using System.Security; + +namespace System.Runtime.CompilerServices +{ + /// <summary> + /// Represents an operation that will schedule continuations when the operation completes. + /// </summary> + public interface INotifyCompletion + { + /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary> + /// <param name="continuation">The action to invoke when the operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + void OnCompleted(Action continuation); + } + + /// <summary> + /// Represents an awaiter used to schedule continuations when an await operation completes. + /// </summary> + public interface ICriticalNotifyCompletion : INotifyCompletion + { + /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary> + /// <param name="continuation">The action to invoke when the operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <remarks>Unlike OnCompleted, UnsafeOnCompleted need not propagate ExecutionContext information.</remarks> + [SecurityCritical] + void UnsafeOnCompleted(Action continuation); + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs new file mode 100644 index 0000000000..f8717cff52 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices +{ +[Serializable] +[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class IUnknownConstantAttribute : CustomConstantAttribute + { + public IUnknownConstantAttribute() + { + } + + public override Object Value + { + get + { + return new UnknownWrapper(null); + } + } + + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs new file mode 100644 index 0000000000..0323fe0cf6 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + using System; + +[Serializable] +[AttributeUsage(AttributeTargets.Property, Inherited = true)] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class IndexerNameAttribute: Attribute + { + public IndexerNameAttribute(String indexerName) + {} + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs new file mode 100644 index 0000000000..ee7807a5dd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace System.Runtime.CompilerServices +{ + using System; + + + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)] + public sealed class InternalsVisibleToAttribute : Attribute + { + private string _assemblyName; + private bool _allInternalsVisible = true; + + public InternalsVisibleToAttribute(string assemblyName) + { + this._assemblyName = assemblyName; + } + + public string AssemblyName + { + get + { + return _assemblyName; + } + } + + public bool AllInternalsVisible + { + get { return _allInternalsVisible; } + set { _allInternalsVisible = value; } + } + } + + /// <summary> + /// If AllInternalsVisible is not true for a friend assembly, the FriendAccessAllowed attribute + /// indicates which internals are shared with that friend assembly. + /// </summary> + [AttributeUsage(AttributeTargets.Class | + AttributeTargets.Constructor | + AttributeTargets.Enum | + AttributeTargets.Event | + AttributeTargets.Field | + AttributeTargets.Interface | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Struct, + AllowMultiple = false, + Inherited = false)] + [FriendAccessAllowed] + internal sealed class FriendAccessAllowedAttribute : Attribute { + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs new file mode 100644 index 0000000000..8b6691c09d --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the modified reference type is a boxed valuetype + public static class IsBoxed + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs new file mode 100644 index 0000000000..d16a853597 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the modified method argument is passed by value + public static class IsByValue + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs new file mode 100644 index 0000000000..210e5997a7 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the modified type is const (i.e. has a const modifier) + public static class IsConst + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs new file mode 100644 index 0000000000..ee40ee7b02 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + [System.Runtime.InteropServices.ComVisible(true)] + public static class IsCopyConstructed + {} +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs new file mode 100644 index 0000000000..480a62175d --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Consider the following C++ method prototypes: + // 1) int foo(int ^arg); + // 2) int foo(int &arg); + // + // Both of these methods will have a .NET type signature that looks the + // same, but when importing a method from a metadata scope, the compiler + // needs to know what the calling syntax should be. This modopt and its + // partner "IsImplicitlyDereferenced" disambiguate reference versus + // pointer arguments. + // + // Indicates that the modified GC reference represents a pointer in a + // method signature. + public static class IsExplicitlyDereferenced + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs new file mode 100644 index 0000000000..ea81cb8ec5 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Consider the following C++ method prototypes: + // 1) int foo(int ^arg); + // 2) int foo(int &arg); + // + // Both of these methods will have a .NET type signature that looks the + // same, but when importing a method from a metadata scope, the compiler + // needs to know what the calling syntax should be. This modopt and its + // partner "IsExplicitlyDereferenced" disambiguate reference versus + // pointer arguments. + // + // Indicates that the modified GC reference represents a reference in a + // method signature. + public static class IsImplicitlyDereferenced + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs new file mode 100644 index 0000000000..013e50f3ea --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the modified method is an intrinsic for which the JIT + // can perform special code generation. + public static class IsJitIntrinsic + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs new file mode 100644 index 0000000000..e8bebfb2d3 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // The C++ standard indicates that a long is always 4-bytes, whereas the + // size of an integer is system dependent (not exceedign sizeof(long)). + // The CLR does not offer a mechanism for encoding this distinction, + // but it is critically important for maintaining language level type + // safety. + // + // Indicates that the modified integer is a standard C++ long. + // Could also be called IsAlternateIntegerType or something else. + public static class IsLong + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs new file mode 100644 index 0000000000..e796d1a1e7 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the modified instance is pinned in memory. + public static class IsPinned + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs new file mode 100644 index 0000000000..e68f4d7751 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // C++ recognizes three char types: signed char, unsigned char, and char. + // When a char is neither signed nor unsigned, it is a char. + // This modopt indicates that the modified instance is a char. + // + // Any compiler could use this to indicate that the user has not specified + // Sign behavior for the given byte. + public static class IsSignUnspecifiedByte + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs new file mode 100644 index 0000000000..dd85914b53 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + // Indicates that the return type is a user defined type + public static class IsUdtReturn + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs new file mode 100644 index 0000000000..ea2fe032c6 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ +[System.Runtime.InteropServices.ComVisible(true)] + public static class IsVolatile + { + // no instantiation, please! + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs new file mode 100644 index 0000000000..4bb9b4eb8f --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + public sealed class IteratorStateMachineAttribute : StateMachineAttribute + { + public IteratorStateMachineAttribute(Type stateMachineType) + : base(stateMachineType) + { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs new file mode 100644 index 0000000000..d081d70070 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices { + + using System; + using System.Reflection; + + // This Enum matchs the miImpl flags defined in corhdr.h. It is used to specify + // certain method properties. + + [Serializable] + [Flags] +[System.Runtime.InteropServices.ComVisible(true)] + public enum MethodImplOptions + { + Unmanaged = System.Reflection.MethodImplAttributes.Unmanaged, + ForwardRef = System.Reflection.MethodImplAttributes.ForwardRef, + PreserveSig = System.Reflection.MethodImplAttributes.PreserveSig, + InternalCall = System.Reflection.MethodImplAttributes.InternalCall, + Synchronized = System.Reflection.MethodImplAttributes.Synchronized, + NoInlining = System.Reflection.MethodImplAttributes.NoInlining, + [System.Runtime.InteropServices.ComVisible(false)] + AggressiveInlining = System.Reflection.MethodImplAttributes.AggressiveInlining, + NoOptimization = System.Reflection.MethodImplAttributes.NoOptimization, + // **** If you add something, update internal MethodImplAttribute(MethodImplAttributes methodImplAttributes)! **** + } + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum MethodCodeType + { + IL = System.Reflection.MethodImplAttributes.IL, + Native = System.Reflection.MethodImplAttributes.Native, + /// <internalonly/> + OPTIL = System.Reflection.MethodImplAttributes.OPTIL, + Runtime = System.Reflection.MethodImplAttributes.Runtime + } + + // Custom attribute to specify additional method properties. +[Serializable] +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)] +[System.Runtime.InteropServices.ComVisible(true)] + sealed public class MethodImplAttribute : Attribute + { + internal MethodImplOptions _val; + public MethodCodeType MethodCodeType; + + internal MethodImplAttribute(MethodImplAttributes methodImplAttributes) + { + MethodImplOptions all = + MethodImplOptions.Unmanaged | MethodImplOptions.ForwardRef | MethodImplOptions.PreserveSig | + MethodImplOptions.InternalCall | MethodImplOptions.Synchronized | + MethodImplOptions.NoInlining | MethodImplOptions.AggressiveInlining | + MethodImplOptions.NoOptimization; + _val = ((MethodImplOptions)methodImplAttributes) & all; + } + + public MethodImplAttribute(MethodImplOptions methodImplOptions) + { + _val = methodImplOptions; + } + + public MethodImplAttribute(short value) + { + _val = (MethodImplOptions)value; + } + + public MethodImplAttribute() + { + } + + public MethodImplOptions Value { get {return _val;} } + } + +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs new file mode 100644 index 0000000000..0d6c759d76 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices { +[Serializable] +[AttributeUsage(AttributeTargets.Struct, Inherited = true), + System.Runtime.InteropServices.ComVisible(true)] + public sealed class NativeCppClassAttribute : Attribute + { + public NativeCppClassAttribute () {} + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs new file mode 100644 index 0000000000..d5e64a1177 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Attribute: ReferenceAssemblyAttribute +** +** Purpose: Identifies an assembly as being a "reference +** assembly", meaning it contains public surface area but +** no usable implementation. Reference assemblies +** should be loadable for introspection, but not execution. +** +============================================================*/ +namespace System.Runtime.CompilerServices +{ + using System; + + [Serializable] + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)] + public sealed class ReferenceAssemblyAttribute : Attribute + { + private String _description; // Maybe ".NET FX v4.0 SP1, partial trust"? + + public ReferenceAssemblyAttribute() + { + } + + public ReferenceAssemblyAttribute(String description) + { + _description = description; + } + + public String Description + { + get { return _description; } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs new file mode 100644 index 0000000000..f363696ebd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace System.Runtime.CompilerServices +{ +[Serializable] +[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, + AllowMultiple=true, Inherited=false)] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class RequiredAttributeAttribute : Attribute + { + private Type requiredContract; + + public RequiredAttributeAttribute (Type requiredContract) + { + this.requiredContract= requiredContract; + } + public Type RequiredContract + { + get { return this.requiredContract; } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs new file mode 100644 index 0000000000..40a9b7c568 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/*============================================================================= +** +** +** +** Purpose: Mark up the program to indicate various legacy or new opt-in behaviors. +** +** +=============================================================================*/ + +namespace System.Runtime.CompilerServices +{ + + using System; + +[Serializable] +[AttributeUsage(AttributeTargets.Assembly, Inherited=false, AllowMultiple=false)] + public sealed class RuntimeCompatibilityAttribute : Attribute + { + // fields + private bool m_wrapNonExceptionThrows; + + // constructors + public RuntimeCompatibilityAttribute() { + // legacy behavior is the default, and m_wrapNonExceptionThrows is implicitly + // false thanks to the CLR's guarantee of zeroed memory. + } + + // properties + + // If a non-CLSCompliant exception (i.e. one that doesn't derive from System.Exception) is + // thrown, should it be wrapped up in a System.Runtime.CompilerServices.RuntimeWrappedException + // instance when presented to catch handlers? + public bool WrapNonExceptionThrows { + get { + return m_wrapNonExceptionThrows; + } + set { + m_wrapNonExceptionThrows = value; + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs new file mode 100644 index 0000000000..d20fe0bffd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -0,0 +1,248 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// RuntimeHelpers +// This class defines a set of static methods that provide support for compilers. +// +// +namespace System.Runtime.CompilerServices { + + using System; + using System.Security; + using System.Runtime; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.ConstrainedExecution; + using System.Runtime.Serialization; + using System.Security.Permissions; + using System.Threading; + using System.Runtime.Versioning; + using System.Diagnostics.Contracts; + + public static class RuntimeHelpers + { +#if FEATURE_CORECLR + // Exposed here as a more appropriate place than on FormatterServices itself, + // which is a high level reflection heavy type. + public static Object GetUninitializedObject(Type type) + { + return FormatterServices.GetUninitializedObject(type); + } +#endif // FEATURE_CORECLR + + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void InitializeArray(Array array,RuntimeFieldHandle fldHandle); + + // GetObjectValue is intended to allow value classes to be manipulated as 'Object' + // but have aliasing behavior of a value class. The intent is that you would use + // this function just before an assignment to a variable of type 'Object'. If the + // value being assigned is a mutable value class, then a shallow copy is returned + // (because value classes have copy semantics), but otherwise the object itself + // is returned. + // + // Note: VB calls this method when they're about to assign to an Object + // or pass it as a parameter. The goal is to make sure that boxed + // value types work identical to unboxed value types - ie, they get + // cloned when you pass them around, and are always passed by value. + // Of course, reference types are not cloned. + // + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object GetObjectValue(Object obj); + + // RunClassConstructor causes the class constructor for the given type to be triggered + // in the current domain. After this call returns, the class constructor is guaranteed to + // have at least been started by some thread. In the absence of class constructor + // deadlock conditions, the call is further guaranteed to have completed. + // + // This call will generate an exception if the specified class constructor threw an + // exception when it ran. + + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void _RunClassConstructor(RuntimeType type); + + public static void RunClassConstructor(RuntimeTypeHandle type) + { + _RunClassConstructor(type.GetRuntimeType()); + } + + // RunModuleConstructor causes the module constructor for the given type to be triggered + // in the current domain. After this call returns, the module constructor is guaranteed to + // have at least been started by some thread. In the absence of module constructor + // deadlock conditions, the call is further guaranteed to have completed. + // + // This call will generate an exception if the specified module constructor threw an + // exception when it ran. + + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void _RunModuleConstructor(System.Reflection.RuntimeModule module); + + public static void RunModuleConstructor(ModuleHandle module) + { + _RunModuleConstructor(module.GetRuntimeModule()); + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static unsafe extern void _PrepareMethod(IRuntimeMethodInfo method, IntPtr* pInstantiation, int cInstantiation); + + [System.Security.SecurityCritical] // auto-generated + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + internal static extern void _CompileMethod(IRuntimeMethodInfo method); + + // Simple (instantiation not required) method. + [System.Security.SecurityCritical] // auto-generated_required + public static void PrepareMethod(RuntimeMethodHandle method) + { + unsafe + { + _PrepareMethod(method.GetMethodInfo(), null, 0); + } + } + + // Generic method or method with generic class with specific instantiation. + [System.Security.SecurityCritical] // auto-generated_required + public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation) + { + unsafe + { + int length; + IntPtr[] instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out length); + fixed (IntPtr* pInstantiation = instantiationHandles) + { + _PrepareMethod(method.GetMethodInfo(), pInstantiation, length); + GC.KeepAlive(instantiation); + } + } + } + + // This method triggers a given delegate to be prepared. This involves preparing the + // delegate's Invoke method and preparing the target of that Invoke. In the case of + // a multi-cast delegate, we rely on the fact that each individual component was prepared + // prior to the Combine. In other words, this service does not navigate through the + // entire multicasting list. + // If our own reliable event sinks perform the Combine (for example AppDomain.DomainUnload), + // then the result is fully prepared. But if a client calls Combine himself and then + // then adds that combination to e.g. AppDomain.DomainUnload, then the client is responsible + // for his own preparation. + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void PrepareDelegate(Delegate d); + + // See comment above for PrepareDelegate + // + // PrepareContractedDelegate weakens this a bit by only assuring that we prepare + // delegates which also have a ReliabilityContract. This is useful for services that + // want to provide opt-in reliability, generally some random event sink providing + // always reliable semantics to random event handlers that are likely to have not + // been written with relability in mind is a lost cause anyway. + // + // NOTE: that for the NGen case you can sidestep the required ReliabilityContract + // by using the [PrePrepareMethod] attribute. + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void PrepareContractedDelegate(Delegate d); + + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetHashCode(Object o); + + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public new static extern bool Equals(Object o1, Object o2); + + public static int OffsetToStringData + { + // This offset is baked in by string indexer intrinsic, so there is no harm + // in getting it baked in here as well. + [System.Runtime.Versioning.NonVersionable] + get { + // Number of bytes from the address pointed to by a reference to + // a String to the first 16-bit character in the String. Skip + // over the MethodTable pointer, & String + // length. Of course, the String reference points to the memory + // after the sync block, so don't count that. + // This property allows C#'s fixed statement to work on Strings. + // On 64 bit platforms, this should be 12 (8+4) and on 32 bit 8 (4+4). +#if BIT64 + return 12; +#else // 32 + return 8; +#endif // BIT64 + } + } + + // This method ensures that there is sufficient stack to execute the average Framework function. + // If there is not enough stack, then it throws System.InsufficientExecutionStackException. + // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack + // below. + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static extern void EnsureSufficientExecutionStack(); + +#if FEATURE_CORECLR + // This method ensures that there is sufficient stack to execute the average Framework function. + // If there is not enough stack, then it return false. + // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack + // below. + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern bool TryEnsureSufficientExecutionStack(); +#endif + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static extern void ProbeForSufficientStack(); + + // This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as + // constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine. + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static void PrepareConstrainedRegions() + { + ProbeForSufficientStack(); + } + + // When we detect a CER with no calls, we can point the JIT to this non-probing version instead + // as we don't need to probe. + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static void PrepareConstrainedRegionsNoOP() + { + } + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + public delegate void TryCode(Object userData); + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + public delegate void CleanupCode(Object userData, bool exceptionThrown); + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData); + +#if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated +#endif + [PrePrepareMethod] + internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userData, bool exceptionThrown) + { + ((CleanupCode)backoutCode)(userData, exceptionThrown); + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs new file mode 100644 index 0000000000..2751d61db7 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: The exception class uses to wrap all non-CLS compliant exceptions. +** +** +=============================================================================*/ + +namespace System.Runtime.CompilerServices { + using System; + using System.Runtime.Serialization; + using System.Runtime.Remoting; + using System.Security.Permissions; + using System.Diagnostics.Contracts; + + [Serializable] + public sealed class RuntimeWrappedException : Exception + { + private RuntimeWrappedException(Object thrownObject) + : base(Environment.GetResourceString("RuntimeWrappedException")) { + SetErrorCode(System.__HResults.COR_E_RUNTIMEWRAPPED); + m_wrappedException = thrownObject; + } + + public Object WrappedException { + get { return m_wrappedException; } + } + + private Object m_wrappedException; + + [System.Security.SecurityCritical] // auto-generated_required + public override void GetObjectData(SerializationInfo info, StreamingContext context) { + if (info==null) { + throw new ArgumentNullException("info"); + } + Contract.EndContractBlock(); + base.GetObjectData(info, context); + info.AddValue("WrappedException", m_wrappedException, typeof(Object)); + } + + internal RuntimeWrappedException(SerializationInfo info, StreamingContext context) + : base(info, context) { + m_wrappedException = info.GetValue("WrappedException", typeof(Object)); + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs new file mode 100644 index 0000000000..91769187cc --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ +[Serializable] +[AttributeUsage(AttributeTargets.Enum)] + public sealed class ScopelessEnumAttribute : Attribute + { + public ScopelessEnumAttribute() + {} + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs new file mode 100644 index 0000000000..38e5538b44 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Struct)] + + + public sealed class SpecialNameAttribute : Attribute + { + public SpecialNameAttribute() { } + } +} + + + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs new file mode 100644 index 0000000000..7c84009e1f --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; + +namespace System.Runtime.CompilerServices +{ + [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + public class StateMachineAttribute : Attribute + { + public Type StateMachineType { get; private set; } + + public StateMachineAttribute(Type stateMachineType) + { + this.StateMachineType = stateMachineType; + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs new file mode 100644 index 0000000000..eb019eecbf --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +namespace System.Runtime.CompilerServices +{ + using System; + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module)] + public sealed class SuppressIldasmAttribute : Attribute + { + public SuppressIldasmAttribute() + { + } + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs new file mode 100644 index 0000000000..6bb36c4bf5 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System.Runtime.InteropServices; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Property)] + + internal sealed class SuppressMergeCheckAttribute : Attribute + { + public SuppressMergeCheckAttribute() + {} + } +} + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs new file mode 100644 index 0000000000..ea6bb96e16 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs @@ -0,0 +1,531 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// +// +// +// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter +// and Task{<T>}.ConfigureAwait. They are meant to be used only by the compiler, e.g. +// +// await nonGenericTask; +// ===================== +// var $awaiter = nonGenericTask.GetAwaiter(); +// if (!$awaiter.IsCompleted) +// { +// SPILL: +// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this); +// return; +// Label: +// UNSPILL; +// } +// $awaiter.GetResult(); +// +// result += await genericTask.ConfigureAwait(false); +// =================================================================================== +// var $awaiter = genericTask.ConfigureAwait(false).GetAwaiter(); +// if (!$awaiter.IsCompleted) +// { +// SPILL; +// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this); +// return; +// Label: +// UNSPILL; +// } +// result += $awaiter.GetResult(); +// +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Contracts; +using System.Security; +using System.Threading; +using System.Threading.Tasks; +using System.Security.Permissions; +using System.Diagnostics.Tracing; + +// NOTE: For performance reasons, initialization is not verified. If a developer +// incorrectly initializes a task awaiter, which should only be done by the compiler, +// NullReferenceExceptions may be generated (the alternative would be for us to detect +// this case and then throw a different exception instead). This is the same tradeoff +// that's made with other compiler-focused value types like List<T>.Enumerator. + +namespace System.Runtime.CompilerServices +{ + /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct TaskAwaiter : ICriticalNotifyCompletion + { + /// <summary>The task being awaited.</summary> + private readonly Task m_task; + + /// <summary>Initializes the <see cref="TaskAwaiter"/>.</summary> + /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to be awaited.</param> + internal TaskAwaiter(Task task) + { + Contract.Requires(task != null, "Constructing an awaiter requires a task to await."); + m_task = task; + } + + /// <summary>Gets whether the task being awaited is completed.</summary> + /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + public bool IsCompleted + { + get { return m_task.IsCompleted; } + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecuritySafeCritical] + public void OnCompleted(Action continuation) + { + OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true); + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecurityCritical] + public void UnsafeOnCompleted(Action continuation) + { + OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false); + } + + /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception> + /// <exception cref="System.Exception">The task completed in a Faulted state.</exception> + public void GetResult() + { + ValidateEnd(m_task); + } + + /// <summary> + /// Fast checks for the end of an await operation to determine whether more needs to be done + /// prior to completing the await. + /// </summary> + /// <param name="task">The awaited task.</param> + internal static void ValidateEnd(Task task) + { + // Fast checks that can be inlined. + if (task.IsWaitNotificationEnabledOrNotRanToCompletion) + { + // If either the end await bit is set or we're not completed successfully, + // fall back to the slower path. + HandleNonSuccessAndDebuggerNotification(task); + } + } + + /// <summary> + /// Ensures the task is completed, triggers any necessary debugger breakpoints for completing + /// the await on the task, and throws an exception if the task did not complete successfully. + /// </summary> + /// <param name="task">The awaited task.</param> + private static void HandleNonSuccessAndDebuggerNotification(Task task) + { + // NOTE: The JIT refuses to inline ValidateEnd when it contains the contents + // of HandleNonSuccessAndDebuggerNotification, hence the separation. + + // Synchronously wait for the task to complete. When used by the compiler, + // the task will already be complete. This code exists only for direct GetResult use, + // for cases where the same exception propagation semantics used by "await" are desired, + // but where for one reason or another synchronous rather than asynchronous waiting is needed. + if (!task.IsCompleted) + { + bool taskCompleted = task.InternalWait(Timeout.Infinite, default(CancellationToken)); + Contract.Assert(taskCompleted, "With an infinite timeout, the task should have always completed."); + } + + // Now that we're done, alert the debugger if so requested + task.NotifyDebuggerOfWaitCompletionIfNecessary(); + + // And throw an exception if the task is faulted or canceled. + if (!task.IsRanToCompletion) ThrowForNonSuccess(task); + } + + /// <summary>Throws an exception to handle a task that completed in a state other than RanToCompletion.</summary> + private static void ThrowForNonSuccess(Task task) + { + Contract.Requires(task.IsCompleted, "Task must have been completed by now."); + Contract.Requires(task.Status != TaskStatus.RanToCompletion, "Task should not be completed successfully."); + + // Handle whether the task has been canceled or faulted + switch (task.Status) + { + // If the task completed in a canceled state, throw an OperationCanceledException. + // This will either be the OCE that actually caused the task to cancel, or it will be a new + // TaskCanceledException. TCE derives from OCE, and by throwing it we automatically pick up the + // completed task's CancellationToken if it has one, including that CT in the OCE. + case TaskStatus.Canceled: + var oceEdi = task.GetCancellationExceptionDispatchInfo(); + if (oceEdi != null) + { + oceEdi.Throw(); + Contract.Assert(false, "Throw() should have thrown"); + } + throw new TaskCanceledException(task); + + // If the task faulted, throw its first exception, + // even if it contained more than one. + case TaskStatus.Faulted: + var edis = task.GetExceptionDispatchInfos(); + if (edis.Count > 0) + { + edis[0].Throw(); + Contract.Assert(false, "Throw() should have thrown"); + break; // Necessary to compile: non-reachable, but compiler can't determine that + } + else + { + Contract.Assert(false, "There should be exceptions if we're Faulted."); + throw task.Exception; + } + } + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="task">The task being awaited.</param> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param> + /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable + [SecurityCritical] + internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext) + { + if (continuation == null) throw new ArgumentNullException("continuation"); + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + // If TaskWait* ETW events are enabled, trace a beginning event for this await + // and set up an ending event to be traced when the asynchronous await completes. + if ( TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled) + { + continuation = OutputWaitEtwEvents(task, continuation); + } + + // Set the continuation onto the awaited task. + task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext, ref stackMark); + } + + /// <summary> + /// Outputs a WaitBegin ETW event, and augments the continuation action to output a WaitEnd ETW event. + /// </summary> + /// <param name="task">The task being awaited.</param> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <returns>The action to use as the actual continuation.</returns> + private static Action OutputWaitEtwEvents(Task task, Action continuation) + { + Contract.Requires(task != null, "Need a task to wait on"); + Contract.Requires(continuation != null, "Need a continuation to invoke when the wait completes"); + + if (Task.s_asyncDebuggingEnabled) + { + Task.AddToActiveTasks(task); + } + + var etwLog = TplEtwProvider.Log; + + if (etwLog.IsEnabled()) + { + // ETW event for Task Wait Begin + var currentTaskAtBegin = Task.InternalCurrent; + + // If this task's continuation is another task, get it. + var continuationTask = AsyncMethodBuilderCore.TryGetContinuationTask(continuation); + etwLog.TaskWaitBegin( + (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id), + (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0), + task.Id, TplEtwProvider.TaskWaitBehavior.Asynchronous, + (continuationTask != null ? continuationTask.Id : 0), System.Threading.Thread.GetDomainID()); + } + + // Create a continuation action that outputs the end event and then invokes the user + // provided delegate. This incurs the allocations for the closure/delegate, but only if the event + // is enabled, and in doing so it allows us to pass the awaited task's information into the end event + // in a purely pay-for-play manner (the alternatively would be to increase the size of TaskAwaiter + // just for this ETW purpose, not pay-for-play, since GetResult would need to know whether a real yield occurred). + return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, () => + { + if (Task.s_asyncDebuggingEnabled) + { + Task.RemoveFromActiveTasks(task.Id); + } + + // ETW event for Task Wait End. + Guid prevActivityId = new Guid(); + bool bEtwLogEnabled = etwLog.IsEnabled(); + if (bEtwLogEnabled) + { + var currentTaskAtEnd = Task.InternalCurrent; + etwLog.TaskWaitEnd( + (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id), + (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0), + task.Id); + + // Ensure the continuation runs under the activity ID of the task that completed for the + // case the antecendent is a promise (in the other cases this is already the case). + if (etwLog.TasksSetActivityIds && (task.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0) + EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(task.Id), out prevActivityId); + } + // Invoke the original continuation provided to OnCompleted. + continuation(); + + if (bEtwLogEnabled) + { + etwLog.TaskWaitContinuationComplete(task.Id); + if (etwLog.TasksSetActivityIds && (task.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0) + EventSource.SetCurrentThreadActivityId(prevActivityId); + } + }); + } + } + + /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct TaskAwaiter<TResult> : ICriticalNotifyCompletion + { + /// <summary>The task being awaited.</summary> + private readonly Task<TResult> m_task; + + /// <summary>Initializes the <see cref="TaskAwaiter{TResult}"/>.</summary> + /// <param name="task">The <see cref="System.Threading.Tasks.Task{TResult}"/> to be awaited.</param> + internal TaskAwaiter(Task<TResult> task) + { + Contract.Requires(task != null, "Constructing an awaiter requires a task to await."); + m_task = task; + } + + /// <summary>Gets whether the task being awaited is completed.</summary> + /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + public bool IsCompleted + { + get { return m_task.IsCompleted; } + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecuritySafeCritical] + public void OnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true); + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecurityCritical] + public void UnsafeOnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false); + } + + /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary> + /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception> + /// <exception cref="System.Exception">The task completed in a Faulted state.</exception> + public TResult GetResult() + { + TaskAwaiter.ValidateEnd(m_task); + return m_task.ResultOnSuccess; + } + } + + /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + public struct ConfiguredTaskAwaitable + { + /// <summary>The task being awaited.</summary> + private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter; + + /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable"/>.</summary> + /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task"/>.</param> + /// <param name="continueOnCapturedContext"> + /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. + /// </param> + internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext) + { + Contract.Requires(task != null, "Constructing an awaitable requires a task to await."); + m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext); + } + + /// <summary>Gets an awaiter for this awaitable.</summary> + /// <returns>The awaiter.</returns> + public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() + { + return m_configuredTaskAwaiter; + } + + /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion + { + /// <summary>The task being awaited.</summary> + private readonly Task m_task; + /// <summary>Whether to attempt marshaling back to the original context.</summary> + private readonly bool m_continueOnCapturedContext; + + /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary> + /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to await.</param> + /// <param name="continueOnCapturedContext"> + /// true to attempt to marshal the continuation back to the original context captured + /// when BeginAwait is called; otherwise, false. + /// </param> + internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext) + { + Contract.Requires(task != null, "Constructing an awaiter requires a task to await."); + m_task = task; + m_continueOnCapturedContext = continueOnCapturedContext; + } + + /// <summary>Gets whether the task being awaited is completed.</summary> + /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + public bool IsCompleted + { + get { return m_task.IsCompleted; } + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecuritySafeCritical] + public void OnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true); + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecurityCritical] + public void UnsafeOnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false); + } + + /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary> + /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception> + /// <exception cref="System.Exception">The task completed in a Faulted state.</exception> + public void GetResult() + { + TaskAwaiter.ValidateEnd(m_task); + } + } + } + + /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + public struct ConfiguredTaskAwaitable<TResult> + { + /// <summary>The underlying awaitable on whose logic this awaitable relies.</summary> + private readonly ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter m_configuredTaskAwaiter; + + /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary> + /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="continueOnCapturedContext"> + /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. + /// </param> + internal ConfiguredTaskAwaitable(Task<TResult> task, bool continueOnCapturedContext) + { + m_configuredTaskAwaiter = new ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter(task, continueOnCapturedContext); + } + + /// <summary>Gets an awaiter for this awaitable.</summary> + /// <returns>The awaiter.</returns> + public ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter GetAwaiter() + { + return m_configuredTaskAwaiter; + } + + /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion + { + /// <summary>The task being awaited.</summary> + private readonly Task<TResult> m_task; + /// <summary>Whether to attempt marshaling back to the original context.</summary> + private readonly bool m_continueOnCapturedContext; + + /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary> + /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param> + /// <param name="continueOnCapturedContext"> + /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. + /// </param> + internal ConfiguredTaskAwaiter(Task<TResult> task, bool continueOnCapturedContext) + { + Contract.Requires(task != null, "Constructing an awaiter requires a task to await."); + m_task = task; + m_continueOnCapturedContext = continueOnCapturedContext; + } + + /// <summary>Gets whether the task being awaited is completed.</summary> + /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + public bool IsCompleted + { + get { return m_task.IsCompleted; } + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecuritySafeCritical] + public void OnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true); + } + + /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary> + /// <param name="continuation">The action to invoke when the await operation completes.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + [SecurityCritical] + public void UnsafeOnCompleted(Action continuation) + { + TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false); + } + + /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary> + /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns> + /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception> + /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception> + /// <exception cref="System.Exception">The task completed in a Faulted state.</exception> + public TResult GetResult() + { + TaskAwaiter.ValidateEnd(m_task); + return m_task.ResultOnSuccess; + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs new file mode 100644 index 0000000000..db04eb9348 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + using System; + using System.Diagnostics.Contracts; + + // We might want to make this inherited someday. But I suspect it shouldn't + // be necessary. + [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] + internal sealed class TypeDependencyAttribute: Attribute + { + + private string typeName; + + public TypeDependencyAttribute (string typeName) + { + if(typeName == null) throw new ArgumentNullException("typeName"); + Contract.EndContractBlock(); + this.typeName = typeName; + } + } + +} + + + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs new file mode 100644 index 0000000000..c1656dcf99 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)] + public sealed class TypeForwardedFromAttribute : Attribute + { + string assemblyFullName; + + private TypeForwardedFromAttribute() + { + // Disallow default constructor + } + + + public TypeForwardedFromAttribute(string assemblyFullName) + { + if (String.IsNullOrEmpty(assemblyFullName)) + { + throw new ArgumentNullException("assemblyFullName"); + } + this.assemblyFullName = assemblyFullName; + } + + public string AssemblyFullName + { + get { + return assemblyFullName; + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs new file mode 100644 index 0000000000..034dad1afe --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Reflection; + +namespace System.Runtime.CompilerServices +{ + using System; + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)] + public sealed class TypeForwardedToAttribute : Attribute + { + private Type _destination; + + public TypeForwardedToAttribute(Type destination) + { + _destination = destination; + } + + public Type Destination + { + get { + return _destination; + } + } + + [System.Security.SecurityCritical] + internal static TypeForwardedToAttribute[] GetCustomAttribute(RuntimeAssembly assembly) + { + Type[] types = null; + RuntimeAssembly.GetForwardedTypes(assembly.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types)); + + TypeForwardedToAttribute[] attributes = new TypeForwardedToAttribute[types.Length]; + for (int i = 0; i < types.Length; ++i) + attributes[i] = new TypeForwardedToAttribute(types[i]); + + return attributes; + } + + } +} + + + + diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs new file mode 100644 index 0000000000..bc210ccb71 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + using System; + +[Serializable] +[AttributeUsage(AttributeTargets.Struct)] + sealed public class UnsafeValueTypeAttribute : Attribute + { + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs new file mode 100644 index 0000000000..b29b39c5bf --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs @@ -0,0 +1,168 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// +// +// +// Compiler-targeted type for switching back into the current execution context, e.g. +// +// await Task.Yield(); +// ===================== +// var $awaiter = Task.Yield().GetAwaiter(); +// if (!$awaiter.IsCompleted) +// { +// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this); +// return; +// Label: +// } +// $awaiter.GetResult(); +// +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +using System; +using System.Security; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Diagnostics.Tracing; +using System.Threading; +using System.Threading.Tasks; +using System.Security.Permissions; + +namespace System.Runtime.CompilerServices +{ + // NOTE: YieldAwaitable currently has no state; while developers are encouraged to use Task.Yield() to produce one, + // no validation is performed to ensure that the developer isn't doing "await new YieldAwaitable()". Such validation + // would require additional, useless state to be stored, and as this is a type in the CompilerServices namespace, and + // as the above example isn't harmful, we take the cheaper approach of not validating anything. + + /// <summary>Provides an awaitable context for switching into a target environment.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + public struct YieldAwaitable + { + /// <summary>Gets an awaiter for this <see cref="YieldAwaitable"/>.</summary> + /// <returns>An awaiter for this awaitable.</returns> + /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks> + public YieldAwaiter GetAwaiter() { return new YieldAwaiter(); } + + /// <summary>Provides an awaiter that switches into a target environment.</summary> + /// <remarks>This type is intended for compiler use only.</remarks> + [HostProtection(Synchronization = true, ExternalThreading = true)] + public struct YieldAwaiter : ICriticalNotifyCompletion + { + /// <summary>Gets whether a yield is not required.</summary> + /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> + public bool IsCompleted { get { return false; } } // yielding is always required for YieldAwaiter, hence false + + /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary> + /// <param name="continuation">The action to invoke asynchronously.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + [SecuritySafeCritical] + public void OnCompleted(Action continuation) + { + QueueContinuation(continuation, flowContext: true); + } + + /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary> + /// <param name="continuation">The action to invoke asynchronously.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + [SecurityCritical] + public void UnsafeOnCompleted(Action continuation) + { + QueueContinuation(continuation, flowContext: false); + } + + /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary> + /// <param name="continuation">The action to invoke asynchronously.</param> + /// <param name="flowContext">true to flow ExecutionContext; false if flowing is not required.</param> + /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception> + [SecurityCritical] + private static void QueueContinuation(Action continuation, bool flowContext) + { + // Validate arguments + if (continuation == null) throw new ArgumentNullException("continuation"); + Contract.EndContractBlock(); + + if (TplEtwProvider.Log.IsEnabled()) + { + continuation = OutputCorrelationEtwEvent(continuation); + } + // Get the current SynchronizationContext, and if there is one, + // post the continuation to it. However, treat the base type + // as if there wasn't a SynchronizationContext, since that's what it + // logically represents. + var syncCtx = SynchronizationContext.CurrentNoFlow; + if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) + { + syncCtx.Post(s_sendOrPostCallbackRunAction, continuation); + } + else + { + // If we're targeting the default scheduler, queue to the thread pool, so that we go into the global + // queue. As we're going into the global queue, we might as well use QUWI, which for the global queue is + // just a tad faster than task, due to a smaller object getting allocated and less work on the execution path. + TaskScheduler scheduler = TaskScheduler.Current; + if (scheduler == TaskScheduler.Default) + { + if (flowContext) + { + ThreadPool.QueueUserWorkItem(s_waitCallbackRunAction, continuation); + } + else + { + ThreadPool.UnsafeQueueUserWorkItem(s_waitCallbackRunAction, continuation); + } + } + // We're targeting a custom scheduler, so queue a task. + else + { + Task.Factory.StartNew(continuation, default(CancellationToken), TaskCreationOptions.PreferFairness, scheduler); + } + } + } + + private static Action OutputCorrelationEtwEvent(Action continuation) + { + int continuationId = Task.NewId(); + Task currentTask = Task.InternalCurrent; + // fire the correlation ETW event + TplEtwProvider.Log.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, (currentTask != null) ? currentTask.Id : 0, continuationId); + + return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, () => + { + var etwLog = TplEtwProvider.Log; + etwLog.TaskWaitContinuationStarted(continuationId); + + // ETW event for Task Wait End. + Guid prevActivityId = new Guid(); + // Ensure the continuation runs under the correlated activity ID generated above + if (etwLog.TasksSetActivityIds) + EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(continuationId), out prevActivityId); + + // Invoke the original continuation provided to OnCompleted. + continuation(); + // Restore activity ID + + if (etwLog.TasksSetActivityIds) + EventSource.SetCurrentThreadActivityId(prevActivityId); + + etwLog.TaskWaitContinuationComplete(continuationId); + }); + + } + + /// <summary>WaitCallback that invokes the Action supplied as object state.</summary> + private static readonly WaitCallback s_waitCallbackRunAction = RunAction; + /// <summary>SendOrPostCallback that invokes the Action supplied as object state.</summary> + private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction; + + /// <summary>Runs an Action delegate provided as state.</summary> + /// <param name="state">The Action delegate to invoke.</param> + private static void RunAction(object state) { ((Action)state)(); } + + /// <summary>Ends the await operation.</summary> + public void GetResult() {} // Nop. It exists purely because the compiler pattern demands it. + } + } +} diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs new file mode 100644 index 0000000000..8ee50da290 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs @@ -0,0 +1,224 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +// JitHelpers +// Low-level Jit Helpers +//////////////////////////////////////////////////////////////////////////////// + +using System; +using System.Threading; +using System.Runtime; +using System.Runtime.Versioning; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; +using System.Security; + +namespace System.Runtime.CompilerServices { + + // Wrapper for address of a string variable on stack + internal struct StringHandleOnStack + { + private IntPtr m_ptr; + + internal StringHandleOnStack(IntPtr pString) + { + m_ptr = pString; + } + } + + // Wrapper for address of a object variable on stack + internal struct ObjectHandleOnStack + { + private IntPtr m_ptr; + + internal ObjectHandleOnStack(IntPtr pObject) + { + m_ptr = pObject; + } + } + + // Wrapper for StackCrawlMark + internal struct StackCrawlMarkHandle + { + private IntPtr m_ptr; + + internal StackCrawlMarkHandle(IntPtr stackMark) + { + m_ptr = stackMark; + } + } + + // Helper class to assist with unsafe pinning of arbitrary objects. The typical usage pattern is: + // fixed (byte * pData = &JitHelpers.GetPinningHelper(value).m_data) + // { + // ... pData is what Object::GetData() returns in VM ... + // } + internal class PinningHelper + { + public byte m_data; + } + + [FriendAccessAllowed] + internal static class JitHelpers + { + // The special dll name to be used for DllImport of QCalls + internal const string QCall = "QCall"; + + // Wraps object variable into a handle. Used to return managed strings from QCalls. + // s has to be a local variable on the stack. + [SecurityCritical] + static internal StringHandleOnStack GetStringHandleOnStack(ref string s) + { + return new StringHandleOnStack(UnsafeCastToStackPointer(ref s)); + } + + // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls. + // o has to be a local variable on the stack. + [SecurityCritical] + static internal ObjectHandleOnStack GetObjectHandleOnStack<T>(ref T o) where T : class + { + return new ObjectHandleOnStack(UnsafeCastToStackPointer(ref o)); + } + + // Wraps StackCrawlMark into a handle. Used to pass StackCrawlMark to QCalls. + // stackMark has to be a local variable on the stack. + [SecurityCritical] + static internal StackCrawlMarkHandle GetStackCrawlMarkHandle(ref StackCrawlMark stackMark) + { + return new StackCrawlMarkHandle(UnsafeCastToStackPointer(ref stackMark)); + } + +#if _DEBUG + [SecurityCritical] + [FriendAccessAllowed] + static internal T UnsafeCast<T>(Object o) where T : class + { + T ret = UnsafeCastInternal<T>(o); + Contract.Assert(ret == (o as T), "Invalid use of JitHelpers.UnsafeCast!"); + return ret; + } + + // The IL body of this method is not critical, but its body will be replaced with unsafe code, so + // this method is effectively critical + [SecurityCritical] + static private T UnsafeCastInternal<T>(Object o) where T : class + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum + { + Contract.Assert(typeof(T).IsEnum + && (Enum.GetUnderlyingType(typeof(T)) == typeof(int) + || Enum.GetUnderlyingType(typeof(T)) == typeof(uint) + || Enum.GetUnderlyingType(typeof(T)) == typeof(short) + || Enum.GetUnderlyingType(typeof(T)) == typeof(ushort) + || Enum.GetUnderlyingType(typeof(T)) == typeof(byte) + || Enum.GetUnderlyingType(typeof(T)) == typeof(sbyte)), + "Error, T must be an 4 byte (or less) enum JitHelpers.UnsafeEnumCast!"); + return UnsafeEnumCastInternal<T>(val); + } + + static private int UnsafeEnumCastInternal<T>(T val) where T : struct // Actually T must be 4 (or less) byte enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum + { + Contract.Assert(typeof(T).IsEnum + && (Enum.GetUnderlyingType(typeof(T)) == typeof(long) + || Enum.GetUnderlyingType(typeof(T)) == typeof(ulong)), + "Error, T must be an 8 byte enum JitHelpers.UnsafeEnumCastLong!"); + return UnsafeEnumCastLongInternal<T>(val); + } + + static private long UnsafeEnumCastLongInternal<T>(T val) where T : struct // Actually T must be 8 byte enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + // Internal method for getting a raw pointer for handles in JitHelpers. + // The reference has to point into a local stack variable in order so it can not be moved by the GC. + [SecurityCritical] + static internal IntPtr UnsafeCastToStackPointer<T>(ref T val) + { + IntPtr p = UnsafeCastToStackPointerInternal<T>(ref val); + Contract.Assert(IsAddressInStack(p), "Pointer not in the stack!"); + return p; + } + + [SecurityCritical] + static private IntPtr UnsafeCastToStackPointerInternal<T>(ref T val) + { + // The body of this function will be replaced by the EE with unsafe code that just returns val!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } +#else // _DEBUG + // The IL body of this method is not critical, but its body will be replaced with unsafe code, so + // this method is effectively critical + [SecurityCritical] + [FriendAccessAllowed] + static internal T UnsafeCast<T>(Object o) where T : class + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum + { + // should be return (int) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum + { + // should be return (long) val; but C# does not allow, runtime does this magically + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } + + [SecurityCritical] + static internal IntPtr UnsafeCastToStackPointer<T>(ref T val) + { + // The body of this function will be replaced by the EE with unsafe code that just returns o!!! + // See getILIntrinsicImplementation for how this happens. + throw new InvalidOperationException(); + } +#endif // _DEBUG + + // Set the given element in the array without any type or range checks + [SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern static internal void UnsafeSetArrayElement(Object[] target, int index, Object element); + + // Used for unsafe pinning of arbitrary objects. + [System.Security.SecurityCritical] // auto-generated + static internal PinningHelper GetPinningHelper(Object o) + { + // This cast is really unsafe - call the private version that does not assert in debug +#if _DEBUG + return UnsafeCastInternal<PinningHelper>(o); +#else + return UnsafeCast<PinningHelper>(o); +#endif + } + +#if _DEBUG + [SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + extern static bool IsAddressInStack(IntPtr ptr); +#endif + } +} diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs new file mode 100644 index 0000000000..e12df10462 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#if FEATURE_CORRUPTING_EXCEPTIONS + +/*============================================================================= +** +** +** +** Purpose: Contains common usage support entities for Corrupting Exceptions +** +** Created: 06/20/2008 +** +** +** +=============================================================================*/ + +namespace System.Runtime.ExceptionServices { + using System; + + // This attribute can be applied to methods to indicate that ProcessCorruptedState + // Exceptions should be delivered to them. + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class HandleProcessCorruptedStateExceptionsAttribute : Attribute + { + public HandleProcessCorruptedStateExceptionsAttribute() + { + } + } +} +#endif // FEATURE_CORRUPTING_EXCEPTIONS diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs new file mode 100644 index 0000000000..7251d901cd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Contains common usage support entities for advanced exception +** handling/processing scenarios. +** +** Created: 11/2/2010 +** +** +** +=============================================================================*/ + +#if FEATURE_EXCEPTIONDISPATCHINFO +namespace System.Runtime.ExceptionServices { + using System; + + // This class defines support for seperating the exception dispatch details + // (like stack trace, watson buckets, etc) from the actual managed exception + // object. This allows us to track error (via the exception object) independent + // of the path the error takes. + // + // This is particularly useful for frameworks like PFX, APM, etc that wish to + // propagate exceptions (i.e. errors to be precise) across threads. + public sealed class ExceptionDispatchInfo + { + // Private members that will hold the relevant details. + private Exception m_Exception; + private string m_remoteStackTrace; + private object m_stackTrace; + private object m_dynamicMethods; + private UIntPtr m_IPForWatsonBuckets; + private Object m_WatsonBuckets; + + private ExceptionDispatchInfo(Exception exception) + { + // Copy over the details we need to save. + m_Exception = exception; + m_remoteStackTrace = exception.RemoteStackTrace; + + // NOTE: don't be tempted to pass the fields for the out params; the containing object + // might be relocated during the call so the pointers will no longer be valid. + object stackTrace; + object dynamicMethods; + m_Exception.GetStackTracesDeepCopy(out stackTrace, out dynamicMethods); + m_stackTrace = stackTrace; + m_dynamicMethods = dynamicMethods; + + m_IPForWatsonBuckets = exception.IPForWatsonBuckets; + m_WatsonBuckets = exception.WatsonBuckets; + } + + internal UIntPtr IPForWatsonBuckets + { + get + { + return m_IPForWatsonBuckets; + } + } + + internal object WatsonBuckets + { + get + { + return m_WatsonBuckets; + } + } + + internal object BinaryStackTraceArray + { + get + { + return m_stackTrace; + } + } + + internal object DynamicMethodArray + { + get + { + return m_dynamicMethods; + } + } + + internal string RemoteStackTrace + { + get + { + return m_remoteStackTrace; + } + } + + // This static method is used to create an instance of ExceptionDispatchInfo for + // the specified exception object and save all the required details that maybe + // needed to be propagated when the exception is "rethrown" on a different thread. + public static ExceptionDispatchInfo Capture(Exception source) + { + if (source == null) + { + throw new ArgumentNullException("source", Environment.GetResourceString("ArgumentNull_Obj")); + } + + return new ExceptionDispatchInfo(source); + } + + // Return the exception object represented by this ExceptionDispatchInfo instance + public Exception SourceException + { + + get + { + return m_Exception; + } + } + + // When a framework needs to "Rethrow" an exception on a thread different (but not necessarily so) from + // where it was thrown, it should invoke this method against the ExceptionDispatchInfo (EDI) + // created for the exception in question. + // + // This method will restore the original stack trace and bucketing details before throwing + // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on + // the original thread. + public void Throw() + { + // Restore the exception dispatch details before throwing the exception. + m_Exception.RestoreExceptionDispatchInfo(this); + throw m_Exception; + } + } +} +#endif // FEATURE_EXCEPTIONDISPATCHINFO diff --git a/src/mscorlib/src/System/Runtime/GcSettings.cs b/src/mscorlib/src/System/Runtime/GcSettings.cs new file mode 100644 index 0000000000..5b4be27757 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/GcSettings.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +namespace System.Runtime { + using System; + using System.Runtime.CompilerServices; + using System.Runtime.ConstrainedExecution; + using System.Security.Permissions; + using System.Diagnostics.Contracts; + + // These settings are the same format as in clr\src\vm\gcpriv.h + // make sure you change that file if you change this file! + + [Serializable] + public enum GCLargeObjectHeapCompactionMode + { + Default = 1, + CompactOnce = 2 + } + + [Serializable] + public enum GCLatencyMode + { + Batch = 0, + Interactive = 1, + LowLatency = 2, + SustainedLowLatency = 3, + NoGCRegion = 4 + } + + public static class GCSettings + { + enum SetLatencyModeStatus + { + Succeeded = 0, + NoGCInProgress = 1 // NoGCRegion is in progress, can't change pause mode. + }; + + public static GCLatencyMode LatencyMode + { + [System.Security.SecuritySafeCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + get + { + return (GCLatencyMode)(GC.GetGCLatencyMode()); + } + + // We don't want to allow this API when hosted. + [System.Security.SecurityCritical] // auto-generated_required + [HostProtection(MayLeakOnAbort = true)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + set + { + if ((value < GCLatencyMode.Batch) || (value > GCLatencyMode.SustainedLowLatency)) + { + throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum")); + } + Contract.EndContractBlock(); + + if (GC.SetGCLatencyMode((int)value) == (int)SetLatencyModeStatus.NoGCInProgress) + throw new InvalidOperationException("The NoGCRegion mode is in progress. End it and then set a different mode."); + } + } + + public static GCLargeObjectHeapCompactionMode LargeObjectHeapCompactionMode + { + [System.Security.SecuritySafeCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + get + { + return (GCLargeObjectHeapCompactionMode)(GC.GetLOHCompactionMode()); + } + + // We don't want to allow this API when hosted. + [System.Security.SecurityCritical] // auto-generated_required + [HostProtection(MayLeakOnAbort = true)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + set + { + if ((value < GCLargeObjectHeapCompactionMode.Default) || + (value > GCLargeObjectHeapCompactionMode.CompactOnce)) + { + throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum")); + } + Contract.EndContractBlock(); + + GC.SetLOHCompactionMode((int)value); + } + } + + public static bool IsServerGC + { + [System.Security.SecuritySafeCritical] // auto-generated + get { + return GC.IsServerGC(); + } + } + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs new file mode 100644 index 0000000000..83eae1c59c --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.InteropServices { + + using System; + using System.Runtime.CompilerServices; + using System.Runtime.Versioning; + + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public struct ArrayWithOffset + { + //private ArrayWithOffset() + //{ + // throw new Exception(); + //} + + [System.Security.SecuritySafeCritical] // auto-generated + public ArrayWithOffset(Object array, int offset) + { + m_array = array; + m_offset = offset; + m_count = 0; + m_count = CalculateCount(); + } + + public Object GetArray() + { + return m_array; + } + + public int GetOffset() + { + return m_offset; + } + + public override int GetHashCode() + { + return m_count + m_offset; + } + + public override bool Equals(Object obj) + { + if (obj is ArrayWithOffset) + return Equals((ArrayWithOffset)obj); + else + return false; + } + + public bool Equals(ArrayWithOffset obj) + { + return obj.m_array == m_array && obj.m_offset == m_offset && obj.m_count == m_count; + } + + public static bool operator ==(ArrayWithOffset a, ArrayWithOffset b) + { + return a.Equals(b); + } + + public static bool operator !=(ArrayWithOffset a, ArrayWithOffset b) + { + return !(a == b); + } + + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern int CalculateCount(); + + private Object m_array; + private int m_offset; + private int m_count; + } + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs new file mode 100644 index 0000000000..06c963a555 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs @@ -0,0 +1,1138 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices{ + + using System; + using System.Reflection; + using System.Diagnostics.Contracts; + + [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class UnmanagedFunctionPointerAttribute : Attribute + { + CallingConvention m_callingConvention; + + public UnmanagedFunctionPointerAttribute(CallingConvention callingConvention) { m_callingConvention = callingConvention; } + + public CallingConvention CallingConvention { get { return m_callingConvention; } } + + public CharSet CharSet; + public bool BestFitMapping; + public bool ThrowOnUnmappableChar; + + // This field is ignored and marshaling behaves as if it was true (for historical reasons). + public bool SetLastError; + + // P/Invoke via delegate always preserves signature, HRESULT swapping is not supported. + //public bool PreserveSig; + } + + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(false)] + public sealed class TypeIdentifierAttribute : Attribute + { + public TypeIdentifierAttribute() { } + public TypeIdentifierAttribute(string scope, string identifier) { Scope_ = scope; Identifier_ = identifier; } + + public String Scope { get { return Scope_; } } + public String Identifier { get { return Identifier_; } } + + internal String Scope_; + internal String Identifier_; + } + + // To be used on methods that sink reverse P/Invoke calls. + // This attribute is a CoreCLR-only security measure, currently ignored by the desktop CLR. + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class AllowReversePInvokeCallsAttribute : Attribute + { + public AllowReversePInvokeCallsAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class DispIdAttribute : Attribute + { + internal int _val; + public DispIdAttribute(int dispId) + { + _val = dispId; + } + public int Value { get { return _val; } } + } + + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public enum ComInterfaceType + { + InterfaceIsDual = 0, + InterfaceIsIUnknown = 1, + InterfaceIsIDispatch = 2, + + [System.Runtime.InteropServices.ComVisible(false)] + InterfaceIsIInspectable = 3, + } + + [AttributeUsage(AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class InterfaceTypeAttribute : Attribute + { + internal ComInterfaceType _val; + public InterfaceTypeAttribute(ComInterfaceType interfaceType) + { + _val = interfaceType; + } + public InterfaceTypeAttribute(short interfaceType) + { + _val = (ComInterfaceType)interfaceType; + } + public ComInterfaceType Value { get { return _val; } } + } + + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComDefaultInterfaceAttribute : Attribute + { + internal Type _val; + + public ComDefaultInterfaceAttribute(Type defaultInterface) + { + _val = defaultInterface; + } + + public Type Value { get { return _val; } } + } + + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public enum ClassInterfaceType + { + None = 0, + AutoDispatch = 1, + AutoDual = 2 + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ClassInterfaceAttribute : Attribute + { + internal ClassInterfaceType _val; + public ClassInterfaceAttribute(ClassInterfaceType classInterfaceType) + { + _val = classInterfaceType; + + } + public ClassInterfaceAttribute(short classInterfaceType) + { + _val = (ClassInterfaceType)classInterfaceType; + } + public ClassInterfaceType Value { get { return _val; } } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComVisibleAttribute : Attribute + { + internal bool _val; + public ComVisibleAttribute(bool visibility) + { + _val = visibility; + } + public bool Value { get { return _val; } } + } + + [AttributeUsage(AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class TypeLibImportClassAttribute : Attribute + { + internal String _importClassName; + public TypeLibImportClassAttribute(Type importClass) + { + _importClassName = importClass.ToString(); + } + public String Value { get { return _importClassName; } } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class LCIDConversionAttribute : Attribute + { + internal int _val; + public LCIDConversionAttribute(int lcid) + { + _val = lcid; + } + public int Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComRegisterFunctionAttribute : Attribute + { + public ComRegisterFunctionAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComUnregisterFunctionAttribute : Attribute + { + public ComUnregisterFunctionAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ProgIdAttribute : Attribute + { + internal String _val; + public ProgIdAttribute(String progId) + { + _val = progId; + } + public String Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ImportedFromTypeLibAttribute : Attribute + { + internal String _val; + public ImportedFromTypeLibAttribute(String tlbFile) + { + _val = tlbFile; + } + public String Value { get {return _val;} } + } + + [Obsolete("The IDispatchImplAttribute is deprecated.", false)] + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public enum IDispatchImplType + { + SystemDefinedImpl = 0, + InternalImpl = 1, + CompatibleImpl = 2, + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, Inherited = false)] + [Obsolete("This attribute is deprecated and will be removed in a future version.", false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class IDispatchImplAttribute : Attribute + { + internal IDispatchImplType _val; + public IDispatchImplAttribute(IDispatchImplType implType) + { + _val = implType; + } + public IDispatchImplAttribute(short implType) + { + _val = (IDispatchImplType)implType; + } + public IDispatchImplType Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Class, Inherited = true)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComSourceInterfacesAttribute : Attribute + { + internal String _val; + public ComSourceInterfacesAttribute(String sourceInterfaces) + { + _val = sourceInterfaces; + } + public ComSourceInterfacesAttribute(Type sourceInterface) + { + _val = sourceInterface.FullName; + } + public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2) + { + _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName; + } + public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3) + { + _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName; + } + public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3, Type sourceInterface4) + { + _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName + "\0" + sourceInterface4.FullName; + } + public String Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.All, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComConversionLossAttribute : Attribute + { + public ComConversionLossAttribute() + { + } + } + +[Serializable] +[Flags()] + [System.Runtime.InteropServices.ComVisible(true)] + public enum TypeLibTypeFlags + { + FAppObject = 0x0001, + FCanCreate = 0x0002, + FLicensed = 0x0004, + FPreDeclId = 0x0008, + FHidden = 0x0010, + FControl = 0x0020, + FDual = 0x0040, + FNonExtensible = 0x0080, + FOleAutomation = 0x0100, + FRestricted = 0x0200, + FAggregatable = 0x0400, + FReplaceable = 0x0800, + FDispatchable = 0x1000, + FReverseBind = 0x2000, + } + +[Serializable] +[Flags()] + [System.Runtime.InteropServices.ComVisible(true)] + public enum TypeLibFuncFlags + { + FRestricted = 0x0001, + FSource = 0x0002, + FBindable = 0x0004, + FRequestEdit = 0x0008, + FDisplayBind = 0x0010, + FDefaultBind = 0x0020, + FHidden = 0x0040, + FUsesGetLastError = 0x0080, + FDefaultCollelem = 0x0100, + FUiDefault = 0x0200, + FNonBrowsable = 0x0400, + FReplaceable = 0x0800, + FImmediateBind = 0x1000, + } + +[Serializable] +[Flags()] + [System.Runtime.InteropServices.ComVisible(true)] + public enum TypeLibVarFlags + { + FReadOnly = 0x0001, + FSource = 0x0002, + FBindable = 0x0004, + FRequestEdit = 0x0008, + FDisplayBind = 0x0010, + FDefaultBind = 0x0020, + FHidden = 0x0040, + FRestricted = 0x0080, + FDefaultCollelem = 0x0100, + FUiDefault = 0x0200, + FNonBrowsable = 0x0400, + FReplaceable = 0x0800, + FImmediateBind = 0x1000, + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class TypeLibTypeAttribute : Attribute + { + internal TypeLibTypeFlags _val; + public TypeLibTypeAttribute(TypeLibTypeFlags flags) + { + _val = flags; + } + public TypeLibTypeAttribute(short flags) + { + _val = (TypeLibTypeFlags)flags; + } + public TypeLibTypeFlags Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class TypeLibFuncAttribute : Attribute + { + internal TypeLibFuncFlags _val; + public TypeLibFuncAttribute(TypeLibFuncFlags flags) + { + _val = flags; + } + public TypeLibFuncAttribute(short flags) + { + _val = (TypeLibFuncFlags)flags; + } + public TypeLibFuncFlags Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Field, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class TypeLibVarAttribute : Attribute + { + internal TypeLibVarFlags _val; + public TypeLibVarAttribute(TypeLibVarFlags flags) + { + _val = flags; + } + public TypeLibVarAttribute(short flags) + { + _val = (TypeLibVarFlags)flags; + } + public TypeLibVarFlags Value { get {return _val;} } + } + + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public enum VarEnum + { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + VT_VECTOR = 0x1000, + VT_ARRAY = 0x2000, + VT_BYREF = 0x4000 + } + + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + // Note that this enum should remain in-sync with the CorNativeType enum in corhdr.h + public enum UnmanagedType + { + Bool = 0x2, // 4 byte boolean value (true != 0, false == 0) + + I1 = 0x3, // 1 byte signed value + + U1 = 0x4, // 1 byte unsigned value + + I2 = 0x5, // 2 byte signed value + + U2 = 0x6, // 2 byte unsigned value + + I4 = 0x7, // 4 byte signed value + + U4 = 0x8, // 4 byte unsigned value + + I8 = 0x9, // 8 byte signed value + + U8 = 0xa, // 8 byte unsigned value + + R4 = 0xb, // 4 byte floating point + + R8 = 0xc, // 8 byte floating point + + Currency = 0xf, // A currency + + BStr = 0x13, // OLE Unicode BSTR + + LPStr = 0x14, // Ptr to SBCS string + + LPWStr = 0x15, // Ptr to Unicode string + + LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string + + ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs) + + IUnknown = 0x19, // COM IUnknown pointer. + + IDispatch = 0x1a, // COM IDispatch pointer + + Struct = 0x1b, // Structure + + Interface = 0x1c, // COM interface + + SafeArray = 0x1d, // OLE SafeArray + + ByValArray = 0x1e, // Array of fixed size (only valid in structs) + + SysInt = 0x1f, // Hardware natural sized signed integer + + SysUInt = 0x20, + + VBByRefStr = 0x22, + + AnsiBStr = 0x23, // OLE BSTR containing SBCS characters + + TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR + + VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0) + + FunctionPtr = 0x26, // Function pointer + + AsAny = 0x28, // Paired with Object type and does runtime marshalling determination + + LPArray = 0x2a, // C style array + + LPStruct = 0x2b, // Pointer to a structure + + CustomMarshaler = 0x2c, + + Error = 0x2d, + + [System.Runtime.InteropServices.ComVisible(false)] + IInspectable = 0x2e, + + [System.Runtime.InteropServices.ComVisible(false)] + HString = 0x2f, // Windows Runtime HSTRING + + [System.Runtime.InteropServices.ComVisible(false)] + LPUTF8Str = 0x30, // UTF8 string + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public unsafe sealed class MarshalAsAttribute : Attribute + { + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter) + { + return GetCustomAttribute(parameter.MetadataToken, parameter.GetRuntimeModule()); + } + + [System.Security.SecurityCritical] // auto-generated + internal static bool IsDefined(RuntimeParameterInfo parameter) + { + return GetCustomAttribute(parameter) != null; + } + + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(RuntimeFieldInfo field) + { + return GetCustomAttribute(field.MetadataToken, field.GetRuntimeModule()); ; + } + + [System.Security.SecurityCritical] // auto-generated + internal static bool IsDefined(RuntimeFieldInfo field) + { + return GetCustomAttribute(field) != null; + } + + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(int token, RuntimeModule scope) + { + UnmanagedType unmanagedType, arraySubType; + VarEnum safeArraySubType; + int sizeParamIndex = 0, sizeConst = 0; + string marshalTypeName = null, marshalCookie = null, safeArrayUserDefinedTypeName = null; + int iidParamIndex = 0; + ConstArray nativeType = ModuleHandle.GetMetadataImport(scope.GetNativeHandle()).GetFieldMarshal(token); + + if (nativeType.Length == 0) + return null; + + MetadataImport.GetMarshalAs(nativeType, + out unmanagedType, out safeArraySubType, out safeArrayUserDefinedTypeName, out arraySubType, out sizeParamIndex, + out sizeConst, out marshalTypeName, out marshalCookie, out iidParamIndex); + + RuntimeType safeArrayUserDefinedType = safeArrayUserDefinedTypeName == null || safeArrayUserDefinedTypeName.Length == 0 ? null : + RuntimeTypeHandle.GetTypeByNameUsingCARules(safeArrayUserDefinedTypeName, scope); + RuntimeType marshalTypeRef = null; + + try + { + marshalTypeRef = marshalTypeName == null ? null : RuntimeTypeHandle.GetTypeByNameUsingCARules(marshalTypeName, scope); + } + catch (System.TypeLoadException) + { + // The user may have supplied a bad type name string causing this TypeLoadException + // Regardless, we return the bad type name + Contract.Assert(marshalTypeName != null); + } + + return new MarshalAsAttribute( + unmanagedType, safeArraySubType, safeArrayUserDefinedType, arraySubType, + (short)sizeParamIndex, sizeConst, marshalTypeName, marshalTypeRef, marshalCookie, iidParamIndex); + } + + internal MarshalAsAttribute(UnmanagedType val, VarEnum safeArraySubType, RuntimeType safeArrayUserDefinedSubType, UnmanagedType arraySubType, + short sizeParamIndex, int sizeConst, string marshalType, RuntimeType marshalTypeRef, string marshalCookie, int iidParamIndex) + { + _val = val; + SafeArraySubType = safeArraySubType; + SafeArrayUserDefinedSubType = safeArrayUserDefinedSubType; + IidParameterIndex = iidParamIndex; + ArraySubType = arraySubType; + SizeParamIndex = sizeParamIndex; + SizeConst = sizeConst; + MarshalType = marshalType; + MarshalTypeRef = marshalTypeRef; + MarshalCookie = marshalCookie; + } + + internal UnmanagedType _val; + public MarshalAsAttribute(UnmanagedType unmanagedType) + { + _val = unmanagedType; + } + public MarshalAsAttribute(short unmanagedType) + { + _val = (UnmanagedType)unmanagedType; + } + public UnmanagedType Value { get { return _val; } } + + // Fields used with SubType = SafeArray. + public VarEnum SafeArraySubType; + public Type SafeArrayUserDefinedSubType; + + // Field used with iid_is attribute (interface pointers). + public int IidParameterIndex; + + // Fields used with SubType = ByValArray and LPArray. + // Array size = parameter(PI) * PM + C + public UnmanagedType ArraySubType; + public short SizeParamIndex; // param index PI + public int SizeConst; // constant C + + // Fields used with SubType = CustomMarshaler + [System.Runtime.InteropServices.ComVisible(true)] + public String MarshalType; // Name of marshaler class + [System.Runtime.InteropServices.ComVisible(true)] + public Type MarshalTypeRef; // Type of marshaler class + public String MarshalCookie; // cookie to pass to marshaler + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComImportAttribute : Attribute + { + internal static Attribute GetCustomAttribute(RuntimeType type) + { + if ((type.Attributes & TypeAttributes.Import) == 0) + return null; + + return new ComImportAttribute(); + } + + internal static bool IsDefined(RuntimeType type) + { + return (type.Attributes & TypeAttributes.Import) != 0; + } + + public ComImportAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class GuidAttribute : Attribute + { + internal String _val; + public GuidAttribute(String guid) + { + _val = guid; + } + public String Value { get { return _val; } } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class PreserveSigAttribute : Attribute + { + internal static Attribute GetCustomAttribute(RuntimeMethodInfo method) + { + if ((method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) == 0) + return null; + + return new PreserveSigAttribute(); + } + + internal static bool IsDefined(RuntimeMethodInfo method) + { + return (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0; + } + + public PreserveSigAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class InAttribute : Attribute + { + internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter) + { + return parameter.IsIn ? new InAttribute() : null; + } + internal static bool IsDefined(RuntimeParameterInfo parameter) + { + return parameter.IsIn; + } + + public InAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class OutAttribute : Attribute + { + internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter) + { + return parameter.IsOut ? new OutAttribute() : null; + } + internal static bool IsDefined(RuntimeParameterInfo parameter) + { + return parameter.IsOut; + } + + public OutAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class OptionalAttribute : Attribute + { + internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter) + { + return parameter.IsOptional ? new OptionalAttribute() : null; + } + internal static bool IsDefined(RuntimeParameterInfo parameter) + { + return parameter.IsOptional; + } + + public OptionalAttribute() + { + } + } + + [Flags] + public enum DllImportSearchPath + { + UseDllDirectoryForDependencies = 0x100, + ApplicationDirectory = 0x200, + UserDirectories = 0x400, + System32 = 0x800, + SafeDirectories = 0x1000, + AssemblyDirectory = 0x2, + LegacyBehavior = 0x0 + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)] + [System.Runtime.InteropServices.ComVisible(false)] + public sealed class DefaultDllImportSearchPathsAttribute : Attribute + { + internal DllImportSearchPath _paths; + public DefaultDllImportSearchPathsAttribute(DllImportSearchPath paths) + { + _paths = paths; + } + + public DllImportSearchPath Paths { get { return _paths; } } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public unsafe sealed class DllImportAttribute : Attribute + { + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(RuntimeMethodInfo method) + { + if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0) + return null; + + MetadataImport scope = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule()); + string entryPoint, dllName = null; + int token = method.MetadataToken; + PInvokeAttributes flags = 0; + + scope.GetPInvokeMap(token, out flags, out entryPoint, out dllName); + + CharSet charSet = CharSet.None; + + switch (flags & PInvokeAttributes.CharSetMask) + { + case PInvokeAttributes.CharSetNotSpec: charSet = CharSet.None; break; + case PInvokeAttributes.CharSetAnsi: charSet = CharSet.Ansi; break; + case PInvokeAttributes.CharSetUnicode: charSet = CharSet.Unicode; break; + case PInvokeAttributes.CharSetAuto: charSet = CharSet.Auto; break; + + // Invalid: default to CharSet.None + default: break; + } + + CallingConvention callingConvention = CallingConvention.Cdecl; + + switch (flags & PInvokeAttributes.CallConvMask) + { + case PInvokeAttributes.CallConvWinapi: callingConvention = CallingConvention.Winapi; break; + case PInvokeAttributes.CallConvCdecl: callingConvention = CallingConvention.Cdecl; break; + case PInvokeAttributes.CallConvStdcall: callingConvention = CallingConvention.StdCall; break; + case PInvokeAttributes.CallConvThiscall: callingConvention = CallingConvention.ThisCall; break; + case PInvokeAttributes.CallConvFastcall: callingConvention = CallingConvention.FastCall; break; + + // Invalid: default to CallingConvention.Cdecl + default: break; + } + + bool exactSpelling = (flags & PInvokeAttributes.NoMangle) != 0; + bool setLastError = (flags & PInvokeAttributes.SupportsLastError) != 0; + bool bestFitMapping = (flags & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled; + bool throwOnUnmappableChar = (flags & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled; + bool preserveSig = (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0; + + return new DllImportAttribute( + dllName, entryPoint, charSet, exactSpelling, setLastError, preserveSig, + callingConvention, bestFitMapping, throwOnUnmappableChar); + } + + internal static bool IsDefined(RuntimeMethodInfo method) + { + return (method.Attributes & MethodAttributes.PinvokeImpl) != 0; + } + + + internal DllImportAttribute( + string dllName, string entryPoint, CharSet charSet, bool exactSpelling, bool setLastError, bool preserveSig, + CallingConvention callingConvention, bool bestFitMapping, bool throwOnUnmappableChar) + { + _val = dllName; + EntryPoint = entryPoint; + CharSet = charSet; + ExactSpelling = exactSpelling; + SetLastError = setLastError; + PreserveSig = preserveSig; + CallingConvention = callingConvention; + BestFitMapping = bestFitMapping; + ThrowOnUnmappableChar = throwOnUnmappableChar; + } + + internal String _val; + + public DllImportAttribute(String dllName) + { + _val = dllName; + } + public String Value { get { return _val; } } + + public String EntryPoint; + public CharSet CharSet; + public bool SetLastError; + public bool ExactSpelling; + public bool PreserveSig; + public CallingConvention CallingConvention; + public bool BestFitMapping; + public bool ThrowOnUnmappableChar; + + } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public unsafe sealed class StructLayoutAttribute : Attribute + { + private const int DEFAULT_PACKING_SIZE = 8; + + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(RuntimeType type) + { + if (!IsDefined(type)) + return null; + + int pack = 0, size = 0; + LayoutKind layoutKind = LayoutKind.Auto; + switch (type.Attributes & TypeAttributes.LayoutMask) + { + case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break; + case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break; + case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break; + default: Contract.Assume(false); break; + } + + CharSet charSet = CharSet.None; + switch (type.Attributes & TypeAttributes.StringFormatMask) + { + case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break; + case TypeAttributes.AutoClass: charSet = CharSet.Auto; break; + case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break; + default: Contract.Assume(false); break; + } + type.GetRuntimeModule().MetadataImport.GetClassLayout(type.MetadataToken, out pack, out size); + + // Metadata parameter checking should not have allowed 0 for packing size. + // The runtime later converts a packing size of 0 to 8 so do the same here + // because it's more useful from a user perspective. + if (pack == 0) + pack = DEFAULT_PACKING_SIZE; + + return new StructLayoutAttribute(layoutKind, pack, size, charSet); + } + + internal static bool IsDefined(RuntimeType type) + { + if (type.IsInterface || type.HasElementType || type.IsGenericParameter) + return false; + + return true; + } + + internal LayoutKind _val; + + internal StructLayoutAttribute(LayoutKind layoutKind, int pack, int size, CharSet charSet) + { + _val = layoutKind; + Pack = pack; + Size = size; + CharSet = charSet; + } + + public StructLayoutAttribute(LayoutKind layoutKind) + { + _val = layoutKind; + } + public StructLayoutAttribute(short layoutKind) + { + _val = (LayoutKind)layoutKind; + } + public LayoutKind Value { get { return _val; } } + public int Pack; + public int Size; + public CharSet CharSet; + } + + [AttributeUsage(AttributeTargets.Field, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public unsafe sealed class FieldOffsetAttribute : Attribute + { + [System.Security.SecurityCritical] // auto-generated + internal static Attribute GetCustomAttribute(RuntimeFieldInfo field) + { + int fieldOffset; + + if (field.DeclaringType != null && + field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out fieldOffset)) + return new FieldOffsetAttribute(fieldOffset); + + return null; + } + + [System.Security.SecurityCritical] // auto-generated + internal static bool IsDefined(RuntimeFieldInfo field) + { + return GetCustomAttribute(field) != null; + } + + internal int _val; + public FieldOffsetAttribute(int offset) + { + _val = offset; + } + public int Value { get { return _val; } } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComAliasNameAttribute : Attribute + { + internal String _val; + public ComAliasNameAttribute(String alias) + { + _val = alias; + } + public String Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class AutomationProxyAttribute : Attribute + { + internal bool _val; + public AutomationProxyAttribute(bool val) + { + _val = val; + } + public bool Value { get {return _val;} } + } + + [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class PrimaryInteropAssemblyAttribute : Attribute + { + internal int _major; + internal int _minor; + + public PrimaryInteropAssemblyAttribute(int major, int minor) + { + _major = major; + _minor = minor; + } + + public int MajorVersion { get {return _major;} } + public int MinorVersion { get {return _minor;} } + } + + [AttributeUsage(AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class CoClassAttribute : Attribute + { + internal Type _CoClass; + + public CoClassAttribute(Type coClass) + { + _CoClass = coClass; + } + + public Type CoClass { get { return _CoClass; } } + } + + [AttributeUsage(AttributeTargets.Interface, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComEventInterfaceAttribute : Attribute + { + internal Type _SourceInterface; + internal Type _EventProvider; + + public ComEventInterfaceAttribute(Type SourceInterface, Type EventProvider) + { + _SourceInterface = SourceInterface; + _EventProvider = EventProvider; + } + + public Type SourceInterface { get {return _SourceInterface;} } + public Type EventProvider { get {return _EventProvider;} } + } + + [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class TypeLibVersionAttribute : Attribute + { + internal int _major; + internal int _minor; + + public TypeLibVersionAttribute(int major, int minor) + { + _major = major; + _minor = minor; + } + + public int MajorVersion { get {return _major;} } + public int MinorVersion { get {return _minor;} } + } + + [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class ComCompatibleVersionAttribute : Attribute + { + internal int _major; + internal int _minor; + internal int _build; + internal int _revision; + + public ComCompatibleVersionAttribute(int major, int minor, int build, int revision) + { + _major = major; + _minor = minor; + _build = build; + _revision = revision; + } + + public int MajorVersion { get {return _major;} } + public int MinorVersion { get {return _minor;} } + public int BuildNumber { get {return _build;} } + public int RevisionNumber { get {return _revision;} } + } + + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class BestFitMappingAttribute : Attribute + { + internal bool _bestFitMapping; + + public BestFitMappingAttribute(bool BestFitMapping) + { + _bestFitMapping = BestFitMapping; + } + + public bool BestFitMapping { get { return _bestFitMapping; } } + public bool ThrowOnUnmappableChar; + } + + [AttributeUsage(AttributeTargets.Module, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class DefaultCharSetAttribute : Attribute + { + internal CharSet _CharSet; + + public DefaultCharSetAttribute(CharSet charSet) + { + _CharSet = charSet; + } + + public CharSet CharSet { get { return _CharSet; } } + } + + [Obsolete("This attribute has been deprecated. Application Domains no longer respect Activation Context boundaries in IDispatch calls.", false)] + [AttributeUsage(AttributeTargets.Assembly, Inherited = false)] + [System.Runtime.InteropServices.ComVisible(true)] + public sealed class SetWin32ContextInIDispatchAttribute : Attribute + { + public SetWin32ContextInIDispatchAttribute() + { + } + } + + [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + [System.Runtime.InteropServices.ComVisible(false)] + public sealed class ManagedToNativeComInteropStubAttribute : Attribute + { + internal Type _classType; + internal String _methodName; + + public ManagedToNativeComInteropStubAttribute(Type classType, String methodName) + { + _classType = classType; + _methodName = methodName; + } + + public Type ClassType { get { return _classType; } } + public String MethodName { get { return _methodName; } } + } + +} + diff --git a/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs new file mode 100644 index 0000000000..58e93a87ea --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Wrapper that is converted to a variant with VT_BSTR. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Security; + using System.Security.Permissions; + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class BStrWrapper + { + [System.Security.SecuritySafeCritical] // auto-generated +#pragma warning disable 618 + [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)] +#pragma warning restore 618 + public BStrWrapper(String value) + { + m_WrappedObject = value; + } + + [System.Security.SecuritySafeCritical] // auto-generated +#pragma warning disable 618 + [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)] +#pragma warning restore 618 + public BStrWrapper(Object value) + { + m_WrappedObject = (String)value; + } + + public String WrappedObject + { + get + { + return m_WrappedObject; + } + } + + private String m_WrappedObject; + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs new file mode 100644 index 0000000000..95b925c3f4 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Exception class for all errors from COM Interop where we don't +** recognize the HResult. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System; + using System.Runtime.Serialization; + using System.Globalization; + using System.Security; + using Microsoft.Win32; + + // Exception for COM Interop errors where we don't recognize the HResult. + // + [ComVisible(true)] + [Serializable] + public class COMException : ExternalException { + public COMException() + : base(Environment.GetResourceString("Arg_COMException")) + { + SetErrorCode(__HResults.E_FAIL); + } + + public COMException(String message) + : base(message) + { + SetErrorCode(__HResults.E_FAIL); + } + + public COMException(String message, Exception inner) + : base(message, inner) { + SetErrorCode(__HResults.E_FAIL); + } + + public COMException(String message,int errorCode) + : base(message) { + SetErrorCode(errorCode); + } + + [SecuritySafeCritical] + internal COMException(int hresult) + : base(Win32Native.GetMessage(hresult)) + { + SetErrorCode(hresult); + } + + internal COMException(String message, int hresult, Exception inner) + : base(message, inner) + { + SetErrorCode(hresult); + } + + protected COMException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + + public override String ToString() { + String message = Message; + String s; + String _className = GetType().ToString(); + s = _className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")"; + + if (!(message == null || message.Length <= 0)) { + s = s + ": " + message; + } + + Exception _innerException = InnerException; + + if (_innerException!=null) { + s = s + " ---> " + _innerException.ToString(); + } + + + if (StackTrace != null) + s += Environment.NewLine + StackTrace; + + return s; + } + + + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs b/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs new file mode 100644 index 0000000000..cf4eb48af0 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices { + + using System; + // Used for the CallingConvention named argument to the DllImport attribute + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum CallingConvention + { + Winapi = 1, + Cdecl = 2, + StdCall = 3, + ThisCall = 4, + FastCall = 5, + } + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs b/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs new file mode 100644 index 0000000000..3c0710a558 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices { + using System; + // Use this in P/Direct function prototypes to specify + // which character set to use when marshalling Strings. + // Using Ansi will marshal the strings as 1 byte char*'s. + // Using Unicode will marshal the strings as 2 byte wchar*'s. + // Generally you probably want to use Auto, which does the + // right thing 99% of the time. + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum CharSet + { + None = 1, // User didn't specify how to marshal strings. + Ansi = 2, // Strings should be marshalled as ANSI 1 byte chars. + Unicode = 3, // Strings should be marshalled as Unicode 2 byte chars. + Auto = 4, // Marshal Strings in the right way for the target system. + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs new file mode 100644 index 0000000000..0bf616d94c --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs @@ -0,0 +1,202 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*============================================================ +** +** +** Purpose: ComEventHelpers APIs allow binding +** managed delegates to COM's connection point based events. +** +**/ +namespace System.Runtime.InteropServices { + // + // #ComEventsFeature + // + // code:#ComEventsFeature defines two public methods allowing to add/remove .NET delegates handling + // events from COM objects. Those methods are defined as part of code:ComEventsHelper static class + // * code:ComEventsHelper.Combine - will create/reuse-an-existing COM event sink and register the + // specified delegate to be raised when corresponding COM event is raised + // * code:ComEventsHelper.Remove + // + // + // To bind an event handler to the COM object you need to provide the following data: + // * rcw - the instance of the COM object you want to bind to + // * iid - Guid of the source interface you want the sink to implement + // * dispid - dispatch identifier of the event on the source interface you are interested in + // * d - delegate to invoked when corresponding COM event is raised. + // + // #ComEventsArchitecture: + // In COM world, events are handled by so-called event sinks. What these are? COM-based Object Models + // (OMs) define "source" interfaces that need to be implemented by the COM clients to receive events. So, + // event sinks are COM objects implementing a source interfaces. Once an event sink is passed to the COM + // server (through a mechanism known as 'binding/advising to connection point'), COM server will be + // calling source interface methods to "fire events" (advising, connection points, firing events etc. - + // is all COM jargon). + // + // There are few interesting obervations about source interfaces. Usually source interfaces are defined + // as 'dispinterface' - meaning that only late-bound invocations on this interface are allowed. Even + // though it is not illegal to use early bound invocations on source interfaces - the practice is + // discouraged because of versioning concerns. + // + // Notice also that each COM server object might define multiple source interfaces and hence have + // multiple connection points (each CP handles exactly one source interface). COM objects that want to + // fire events are required to implement IConnectionPointContainer interface which is used by the COM + // clients to discovery connection poitns - objects implementing IConnectionPoint interface. Once + // connection point is found - clients can bind to it using IConnectionPoint::Advise (see + // code:ComEventsSink.Advise). + // + // The idea behind code:#ComEventsFeature is to write a "universal event sink" COM component that is + // generic enough to handle all late-bound event firings and invoke corresponding COM delegates (through + // reflection). + // + // When delegate is registered (using code:ComEventsHelper.Combine) we will verify we have corresponding + // event sink created and bound. + // + // But what happens when COM events are fired? code:ComEventsSink.Invoke implements IDispatch::Invoke method + // and this is the entry point that is called. Once our event sink is invoked, we need to find the + // corresponding delegate to invoke . We need to match the dispid of the call that is coming in to a + // dispid of .NET delegate that has been registered for this object. Once this is found we do call the + // delegates using reflection (code:ComEventsMethod.Invoke). + // + // #ComEventsArgsMarshalling + // Notice, that we may not have a delegate registered against every method on the source interface. If we + // were to marshal all the input parameters for methods that do not reach user code - we would end up + // generatic RCWs that are not reachable for user code (the inconvenience it might create is there will + // be RCWs that users can not call Marshal.ReleaseComObject on to explicitly manage the lifetime of these + // COM objects). The above behavior was one of the shortcoimings of legacy TLBIMP's implementation of COM + // event sinking. In our code we will not marshal any data if there is no delegate registered to handle + // the event. (code:ComEventsMethod.Invoke) + // + // #ComEventsFinalization: + // Additional area of interest is when COM sink should be unadvised from the connection point. Legacy + // TLBIMP's implementation of COM event sinks will unadvises the sink when corresponding RCW is GCed. + // This is achieved by rooting the event sinks in a finalizable object stored in RCW's property bag + // (using Marshal.SetComObjectData). Hence, once RCW is no longer reachable - the finalizer is called and + // it would unadvise all the event sinks. We are employing the same strategy here. See storing an + // instance in the RCW at code:ComEventsInfo.FromObject and undadvsing the sinks at + // code:ComEventsInfo.~ComEventsInfo + // + // Classes of interest: + // * code:ComEventsHelpers - defines public methods but there are also a number of internal classes that + // implement the actual COM event sink: + // * code:ComEventsInfo - represents a finalizable container for all event sinks for a particular RCW. + // Lifetime of this instance corresponds to the lifetime of the RCW object + // * code:ComEventsSink - represents a single event sink. Maintains an internal pointer to the next + // instance (in a singly linked list). A collection of code:ComEventsSink is stored at + // code:ComEventsInfo._sinks + // * code:ComEventsMethod - represents a single method from the source interface which has .NET delegates + // attached to it. Maintains an internal pointer to the next instance (in a singly linked list). A + // collection of code:ComEventMethod is stored at code:ComEventsSink._methods + // + // #ComEventsRetValIssue: + // Issue: normally, COM events would not return any value. However, it may happen as described in + // http://support.microsoft.com/kb/810228. Such design might represent a problem for us - e.g. what is + // the return value of a chain of delegates - is it the value of the last call in the chain or the the + // first one? As the above KB article indicates, in cases where OM has events returning values, it is + // suggested that people implement their event sink by explicitly implementing the source interface. This + // means that the problem is already quite complex and we should not be dealing with it - see + // code:ComEventsMethod.Invoke + + using System; + using System.Runtime.Remoting; + + /// <summary> + /// The static methods provided in ComEventsHelper allow using .NET delegates to subscribe to events + /// raised COM objects. + /// </summary> + public static class ComEventsHelper { + + /// <summary> + /// Adds a delegate to the invocation list of events originating from the COM object. + /// </summary> + /// <param name="rcw">COM object firing the events the caller would like to respond to</param> + /// <param name="iid">identifier of the source interface used by COM object to fire events</param> + /// <param name="dispid">dispatch identifier of the method on the source interface</param> + /// <param name="d">delegate to invoke when specifed COM event is fired</param> + [System.Security.SecurityCritical] + public static void Combine(object rcw, Guid iid, int dispid, System.Delegate d) { + + rcw = UnwrapIfTransparentProxy(rcw); + + lock (rcw) { + ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw); + + ComEventsSink sink = eventsInfo.FindSink(ref iid); + if (sink == null) { + sink = eventsInfo.AddSink(ref iid); + } + + + ComEventsMethod method = sink.FindMethod(dispid); + if (method == null) { + method = sink.AddMethod(dispid); + } + + method.AddDelegate(d); + } + } + + /// <summary> + /// Removes a delegate from the invocation list of events originating from the COM object. + /// </summary> + /// <param name="rcw">COM object the delegate is attached to</param> + /// <param name="iid">identifier of the source interface used by COM object to fire events</param> + /// <param name="dispid">dispatch identifier of the method on the source interface</param> + /// <param name="d">delegate to remove from the invocation list</param> + /// <returns></returns> + [System.Security.SecurityCritical] + public static Delegate Remove(object rcw, Guid iid, int dispid, System.Delegate d) { + + rcw = UnwrapIfTransparentProxy(rcw); + + lock (rcw) { + + ComEventsInfo eventsInfo = ComEventsInfo.Find(rcw); + if (eventsInfo == null) + return null; + ComEventsSink sink = eventsInfo.FindSink(ref iid); + if (sink == null) + return null; + ComEventsMethod method = sink.FindMethod(dispid); + if (method == null) + return null; + + method.RemoveDelegate(d); + + if (method.Empty) { + // removed the last event handler for this dispid - need to remove dispid handler + method = sink.RemoveMethod(method); + } + if (method == null) { + // removed last dispid handler for this sink - need to remove the sink + sink = eventsInfo.RemoveSink(sink); + } + if (sink == null) { + // removed last sink for this rcw - need to remove all traces of event info + Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), null); + GC.SuppressFinalize(eventsInfo); + } + + return d; + } + } + + [System.Security.SecurityCritical] + internal static object UnwrapIfTransparentProxy(object rcw) { +#if FEATURE_REMOTING + if (RemotingServices.IsTransparentProxy(rcw)) { + IntPtr punk = Marshal.GetIUnknownForObject(rcw); + try { + rcw = Marshal.GetObjectForIUnknown(punk); + } finally { + Marshal.Release(punk); + } + } +#endif + return rcw; + } + } + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs new file mode 100644 index 0000000000..6feb52445d --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*============================================================ +** +** +** Purpose: part of ComEventHelpers APIs which allow binding +** managed delegates to COM's connection point based events. +** +**/ + +namespace System.Runtime.InteropServices { + + using System; + using ComTypes = System.Runtime.InteropServices.ComTypes; + + // see code:ComEventsHelper#ComEventsArchitecture + [System.Security.SecurityCritical] + internal class ComEventsInfo { + + +#region fields + + private ComEventsSink _sinks; + private object _rcw; + +#endregion + + +#region ctor/dtor + + ComEventsInfo(object rcw) { + _rcw = rcw; + } + + [System.Security.SecuritySafeCritical] + ~ComEventsInfo() { + // see code:ComEventsHelper#ComEventsFinalization + _sinks = ComEventsSink.RemoveAll(_sinks); + } + +#endregion + + +#region static methods + + [System.Security.SecurityCritical] + internal static ComEventsInfo Find(object rcw) { + return (ComEventsInfo)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo)); + } + + // it is caller's responsibility to call this method under lock(rcw) + [System.Security.SecurityCritical] + internal static ComEventsInfo FromObject(object rcw) { + ComEventsInfo eventsInfo = Find(rcw); + if (eventsInfo == null) { + eventsInfo = new ComEventsInfo(rcw); + Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), eventsInfo); + } + return eventsInfo; + } + +#endregion + + +#region internal methods + + internal ComEventsSink FindSink(ref Guid iid) { + return ComEventsSink.Find(_sinks, ref iid); + } + + // it is caller's responsibility to call this method under lock(rcw) + internal ComEventsSink AddSink(ref Guid iid) { + ComEventsSink sink = new ComEventsSink(_rcw, iid); + _sinks = ComEventsSink.Add(_sinks, sink); + + return _sinks; + } + + // it is caller's responsibility to call this method under lock(rcw) + [System.Security.SecurityCritical] + internal ComEventsSink RemoveSink(ComEventsSink sink) { + _sinks = ComEventsSink.Remove(_sinks, sink); + return _sinks; + } + +#endregion + + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs new file mode 100644 index 0000000000..2da0c5eea3 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs @@ -0,0 +1,246 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*============================================================ +** +** +** Purpose: part of ComEventHelpers APIs which allow binding +** managed delegates to COM's connection point based events. +** +**/ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Reflection; + + +namespace System.Runtime.InteropServices { + + // see code:ComEventsHelper#ComEventsArchitecture + internal class ComEventsMethod { + + // This delegate wrapper class handles dynamic invocation of delegates. The reason for the wrapper's + // existence is that under certain circumstances we need to coerce arguments to types expected by the + // delegates signature. Normally, reflection (Delegate.DynamicInvoke) handles types coercion + // correctly but one known case is when the expected signature is 'ref Enum' - in this case + // reflection by design does not do the coercion. Since we need to be compatible with COM interop + // handling of this scenario - we are pre-processing delegate's signature by looking for 'ref enums' + // and cache the types required for such coercion. + internal class DelegateWrapper { + private Delegate _d; + + private bool _once = false; + private int _expectedParamsCount; + private Type[] _cachedTargetTypes; + + public DelegateWrapper(Delegate d) { + _d = d; + } + + public Delegate Delegate { + get { return _d; } + set { _d = value; } + } + + public object Invoke(object[] args) { + if (_d == null) + return null; + + if (_once == false) { + PreProcessSignature(); + _once = true; + } + + if (_cachedTargetTypes != null && _expectedParamsCount == args.Length) { + for (int i = 0; i < _expectedParamsCount; i++) { + if (_cachedTargetTypes[i] != null) { + args[i] = Enum.ToObject(_cachedTargetTypes[i], args[i]); + } + } + } + + return _d.DynamicInvoke(args); + } + + private void PreProcessSignature() { + ParameterInfo[] parameters = _d.Method.GetParameters(); + _expectedParamsCount = parameters.Length; + + Type[] enumTypes = new Type[_expectedParamsCount]; + + bool needToHandleCoercion = false; + + for (int i = 0; i < _expectedParamsCount; i++) { + ParameterInfo pi = parameters[i]; + // recognize only 'ref Enum' signatures and cache + // both enum type and the underlying type. + if (pi.ParameterType.IsByRef && + pi.ParameterType.HasElementType && + pi.ParameterType.GetElementType().IsEnum) { + + needToHandleCoercion = true; + enumTypes[i] = pi.ParameterType.GetElementType(); + } + } + + if (needToHandleCoercion == true) { + _cachedTargetTypes = enumTypes; + } + } + } + + #region private fields + + /// <summary> + /// Invoking ComEventsMethod means invoking a multi-cast delegate attached to it. + /// Since multicast delegate's built-in chaining supports only chaining instances of the same type, + /// we need to complement this design by using an explicit linked list data structure. + /// </summary> + private DelegateWrapper [] _delegateWrappers; + + private int _dispid; + private ComEventsMethod _next; + + #endregion + + + #region ctor + + internal ComEventsMethod(int dispid) { + _delegateWrappers = null; + _dispid = dispid; + } + + #endregion + + + #region static internal methods + + internal static ComEventsMethod Find(ComEventsMethod methods, int dispid) { + while (methods != null && methods._dispid != dispid) { + methods = methods._next; + } + return methods; + } + + internal static ComEventsMethod Add(ComEventsMethod methods, ComEventsMethod method) { + method._next = methods; + return method; + } + + internal static ComEventsMethod Remove(ComEventsMethod methods, ComEventsMethod method) { + if (methods == method) { + methods = methods._next; + } else { + ComEventsMethod current = methods; + while (current != null && current._next != method) + current = current._next; + if (current != null) + current._next = method._next; + } + + return methods; + } + + #endregion + + + #region public properties / methods + + internal int DispId { + get { return _dispid; } + } + + internal bool Empty { + get { return _delegateWrappers == null || _delegateWrappers.Length == 0; } + } + + internal void AddDelegate(Delegate d) { + int count = 0; + if (_delegateWrappers != null) { + count = _delegateWrappers.Length; + } + + for (int i = 0; i < count; i++) { + if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) { + _delegateWrappers[i].Delegate = Delegate.Combine(_delegateWrappers[i].Delegate, d); + return; + } + } + + DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count + 1]; + if (count > 0) { + _delegateWrappers.CopyTo(newDelegateWrappers, 0); + } + + DelegateWrapper wrapper = new DelegateWrapper(d); + newDelegateWrappers[count] = wrapper; + + _delegateWrappers = newDelegateWrappers; + } + + internal void RemoveDelegate(Delegate d) { + + int count = _delegateWrappers.Length; + int removeIdx = -1; + + for (int i = 0; i < count; i++) { + if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) { + removeIdx = i; + break; + } + } + + if (removeIdx < 0) + return; + + Delegate newDelegate = Delegate.Remove(_delegateWrappers[removeIdx].Delegate, d); + if (newDelegate != null) { + _delegateWrappers[removeIdx].Delegate = newDelegate; + return; + } + + // now remove the found entry from the _delegates array + + if (count == 1) { + _delegateWrappers = null; + return; + } + + DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count - 1]; + int j = 0; + while (j < removeIdx) { + newDelegateWrappers[j] = _delegateWrappers[j]; + j++; + } + while (j < count-1) { + newDelegateWrappers[j] = _delegateWrappers[j + 1]; + j++; + } + + _delegateWrappers = newDelegateWrappers; + } + + internal object Invoke(object[] args) { + BCLDebug.Assert(Empty == false, "event sink is executed but delegates list is empty"); + + // Issue: see code:ComEventsHelper#ComEventsRetValIssue + object result = null; + DelegateWrapper[] invocationList = _delegateWrappers; + foreach (DelegateWrapper wrapper in invocationList) { + if (wrapper == null || wrapper.Delegate == null) + continue; + + result = wrapper.Invoke(args); + } + + return result; + } + + #endregion + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs new file mode 100644 index 0000000000..a414eff3a1 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs @@ -0,0 +1,286 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*============================================================ +** +** +** Purpose: part of ComEventHelpers APIs which allow binding +** managed delegates to COM's connection point based events. +** +**/ + +namespace System.Runtime.InteropServices { + using System; + using System.Diagnostics; + + // see code:ComEventsHelper#ComEventsArchitecture + [System.Security.SecurityCritical] + internal class ComEventsSink : NativeMethods.IDispatch, ICustomQueryInterface + { +#region private fields + + private Guid _iidSourceItf; + private ComTypes.IConnectionPoint _connectionPoint; + private int _cookie; + private ComEventsMethod _methods; + private ComEventsSink _next; + +#endregion + + +#region ctor + + internal ComEventsSink(object rcw, Guid iid) { + _iidSourceItf = iid; + this.Advise(rcw); + } + +#endregion + + +#region static members + + internal static ComEventsSink Find(ComEventsSink sinks, ref Guid iid) { + + ComEventsSink sink = sinks; + while (sink != null && sink._iidSourceItf != iid) { + sink = sink._next; + } + + return sink; + } + + internal static ComEventsSink Add(ComEventsSink sinks, ComEventsSink sink) { + sink._next = sinks; + return sink; + } + + [System.Security.SecurityCritical] + internal static ComEventsSink RemoveAll(ComEventsSink sinks) { + while (sinks != null) { + sinks.Unadvise(); + sinks = sinks._next; + } + + return null; + } + + [System.Security.SecurityCritical] + internal static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) { + BCLDebug.Assert(sinks != null, "removing event sink from empty sinks collection"); + BCLDebug.Assert(sink != null, "specify event sink is null"); + + if (sink == sinks) { + sinks = sinks._next; + } else { + ComEventsSink current = sinks; + while (current != null && current._next != sink) + current = current._next; + + if (current != null) { + current._next = sink._next; + } + } + + sink.Unadvise(); + + return sinks; + } + +#endregion + + +#region public methods + + public ComEventsMethod RemoveMethod(ComEventsMethod method) { + _methods = ComEventsMethod.Remove(_methods, method); + return _methods; + } + + public ComEventsMethod FindMethod(int dispid) { + return ComEventsMethod.Find(_methods, dispid); + } + + public ComEventsMethod AddMethod(int dispid) { + ComEventsMethod method = new ComEventsMethod(dispid); + _methods = ComEventsMethod.Add(_methods, method); + return method; + } + +#endregion + + +#region IDispatch Members + + [System.Security.SecurityCritical] + void NativeMethods.IDispatch.GetTypeInfoCount(out uint pctinfo) { + pctinfo = 0; + } + + [System.Security.SecurityCritical] + void NativeMethods.IDispatch.GetTypeInfo(uint iTInfo, int lcid, out IntPtr info) { + throw new NotImplementedException(); + } + + [System.Security.SecurityCritical] + void NativeMethods.IDispatch.GetIDsOfNames(ref Guid iid, string[] names, uint cNames, int lcid, int[] rgDispId) { + throw new NotImplementedException(); + } + + private const VarEnum VT_BYREF_VARIANT = VarEnum.VT_BYREF | VarEnum.VT_VARIANT; + private const VarEnum VT_TYPEMASK = (VarEnum) 0x0fff; + private const VarEnum VT_BYREF_TYPEMASK = VT_TYPEMASK | VarEnum.VT_BYREF; + + private static unsafe Variant *GetVariant(Variant *pSrc) + { + if (pSrc->VariantType == VT_BYREF_VARIANT) + { + // For VB6 compatibility reasons, if the VARIANT is a VT_BYREF | VT_VARIANT that + // contains another VARIANT with VT_BYREF | VT_VARIANT, then we need to extract the + // inner VARIANT and use it instead of the outer one. Note that if the inner VARIANT + // is VT_BYREF | VT_VARIANT | VT_ARRAY, it will pass the below test too. + Variant *pByRefVariant = (Variant *)pSrc->AsByRefVariant; + if ((pByRefVariant->VariantType & VT_BYREF_TYPEMASK) == VT_BYREF_VARIANT) + return (Variant *)pByRefVariant; + } + + return pSrc; + } + + [System.Security.SecurityCritical] + unsafe void NativeMethods.IDispatch.Invoke( + int dispid, + ref Guid riid, + int lcid, + ComTypes.INVOKEKIND wFlags, + ref ComTypes.DISPPARAMS pDispParams, + IntPtr pvarResult, + IntPtr pExcepInfo, + IntPtr puArgErr) { + + ComEventsMethod method = FindMethod(dispid); + if (method == null) + return; + + // notice the unsafe pointers we are using. This is to avoid unnecessary + // arguments marshalling. see code:ComEventsHelper#ComEventsArgsMarshalling + + object [] args = new object[pDispParams.cArgs]; + int [] byrefsMap = new int[pDispParams.cArgs]; + bool [] usedArgs = new bool[pDispParams.cArgs]; + + Variant* pvars = (Variant*)pDispParams.rgvarg; + int* pNamedArgs = (int*)pDispParams.rgdispidNamedArgs; + + // copy the named args (positional) as specified + int i; + int pos; + for (i = 0; i < pDispParams.cNamedArgs; i++) { + pos = pNamedArgs[i]; + + Variant* pvar = GetVariant(&pvars[i]); + args[pos] = pvar->ToObject(); + usedArgs[pos] = true; + + if (pvar->IsByRef) { + byrefsMap[pos] = i; + } else { + byrefsMap[pos] = -1; + } + } + + // copy the rest of the arguments in the reverse order + pos = 0; + for (; i < pDispParams.cArgs; i++) { + // find the next unassigned argument + while (usedArgs[pos]) { + ++pos; + } + + Variant* pvar = GetVariant(&pvars[pDispParams.cArgs - 1 - i]); + args[pos] = pvar->ToObject(); + + if (pvar->IsByRef) + byrefsMap[pos] = pDispParams.cArgs - 1 - i; + else + byrefsMap[pos] = -1; + + pos++; + } + + // Do the actual delegate invocation + object result; + result = method.Invoke(args); + + // convert result to VARIANT + if (pvarResult != IntPtr.Zero) { + Marshal.GetNativeVariantForObject(result, pvarResult); + } + + // Now we need to marshal all the byrefs back + for (i = 0; i < pDispParams.cArgs; i++) { + int idxToPos = byrefsMap[i]; + if (idxToPos == -1) + continue; + + GetVariant(&pvars[idxToPos])->CopyFromIndirect(args[i]); + } + } + +#endregion + + static Guid IID_IManagedObject = new Guid("{C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4}"); + + [System.Security.SecurityCritical] + CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv) { + ppv = IntPtr.Zero; + if (iid == this._iidSourceItf || iid == typeof(NativeMethods.IDispatch).GUID) { + ppv = Marshal.GetComInterfaceForObject(this, typeof(NativeMethods.IDispatch), CustomQueryInterfaceMode.Ignore); + return CustomQueryInterfaceResult.Handled; + } + else if (iid == IID_IManagedObject) + { + return CustomQueryInterfaceResult.Failed; + } + + return CustomQueryInterfaceResult.NotHandled; + } + +#region private methods + + + private void Advise(object rcw) { + BCLDebug.Assert(_connectionPoint == null, "comevent sink is already advised"); + + ComTypes.IConnectionPointContainer cpc = (ComTypes.IConnectionPointContainer)rcw; + ComTypes.IConnectionPoint cp; + cpc.FindConnectionPoint(ref _iidSourceItf, out cp); + + object sinkObject = this; + + cp.Advise(sinkObject, out _cookie); + + _connectionPoint = cp; + } + + [System.Security.SecurityCritical] + private void Unadvise() { + BCLDebug.Assert(_connectionPoint != null, "can not unadvise from empty connection point"); + + try { + _connectionPoint.Unadvise(_cookie); + Marshal.ReleaseComObject(_connectionPoint); + } catch (System.Exception) { + // swallow all exceptions on unadvise + // the host may not be available at this point + } finally { + _connectionPoint = null; + } + + } + +#endregion + }; +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs new file mode 100644 index 0000000000..3be2a56da5 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices { + + using System; + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum ComMemberType + { + Method = 0, + PropGet = 1, + PropSet = 2 + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs new file mode 100644 index 0000000000..aac3f59d0f --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IBindCtx interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [StructLayout(LayoutKind.Sequential)] + + public struct BIND_OPTS + { + public int cbStruct; + public int grfFlags; + public int grfMode; + public int dwTickCountDeadline; + } + + [Guid("0000000e-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IBindCtx + { + void RegisterObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk); + void RevokeObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk); + void ReleaseBoundObjects(); + void SetBindOptions([In()] ref BIND_OPTS pbindopts); + void GetBindOptions(ref BIND_OPTS pbindopts); + void GetRunningObjectTable(out IRunningObjectTable pprot); + void RegisterObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] Object punk); + void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] out Object ppunk); + void EnumObjectParam(out IEnumString ppenum); + [PreserveSig] + int RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs new file mode 100644 index 0000000000..f70973e60d --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IConnectionPoint interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("B196B286-BAB4-101A-B69C-00AA00341D07")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IConnectionPoint + { + void GetConnectionInterface(out Guid pIID); + void GetConnectionPointContainer(out IConnectionPointContainer ppCPC); + void Advise([MarshalAs(UnmanagedType.Interface)] Object pUnkSink, out int pdwCookie); + void Unadvise(int dwCookie); + void EnumConnections(out IEnumConnections ppEnum); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs new file mode 100644 index 0000000000..fffff3c170 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IConnectionPointContainer interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("B196B284-BAB4-101A-B69C-00AA00341D07")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IConnectionPointContainer + { + void EnumConnectionPoints(out IEnumConnectionPoints ppEnum); + void FindConnectionPoint([In] ref Guid riid, out IConnectionPoint ppCP); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs new file mode 100644 index 0000000000..d667925b7e --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IEnumConnectionPoints interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("B196B285-BAB4-101A-B69C-00AA00341D07")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumConnectionPoints + { + [PreserveSig] + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IConnectionPoint[] rgelt, IntPtr pceltFetched); + [PreserveSig] + int Skip(int celt); + void Reset(); + void Clone(out IEnumConnectionPoints ppenum); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs new file mode 100644 index 0000000000..8a2b4f0e6f --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IEnumConnections interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct CONNECTDATA + { + [MarshalAs(UnmanagedType.Interface)] + public Object pUnk; + public int dwCookie; + } + + [Guid("B196B287-BAB4-101A-B69C-00AA00341D07")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumConnections + { + [PreserveSig] + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] CONNECTDATA[] rgelt, IntPtr pceltFetched); + [PreserveSig] + int Skip(int celt); + void Reset(); + void Clone(out IEnumConnections ppenum); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs new file mode 100644 index 0000000000..57994b66bc --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IEnumMoniker interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00000102-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumMoniker + { + [PreserveSig] + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IMoniker[] rgelt, IntPtr pceltFetched); + [PreserveSig] + int Skip(int celt); + void Reset(); + void Clone(out IEnumMoniker ppenum); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs new file mode 100644 index 0000000000..f1e9233581 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IEnumString interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00000101-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumString + { + [PreserveSig] + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0), Out] String[] rgelt, IntPtr pceltFetched); + [PreserveSig] + int Skip(int celt); + void Reset(); + void Clone(out IEnumString ppenum); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs new file mode 100644 index 0000000000..ea9b74b7c1 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IEnumVARIANT interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00020404-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumVARIANT + { + [PreserveSig] + int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0), Out] object[] rgVar, IntPtr pceltFetched); + + [PreserveSig] + int Skip(int celt); + + [PreserveSig] + int Reset(); + + IEnumVARIANT Clone(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs new file mode 100644 index 0000000000..1a13399a88 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*========================================================================== +** +** Interface: IEnumerable +** +** +** Purpose: +** This interface is redefined here since the original IEnumerable interface +** has all its methods marked as ecall's since it is a managed standard +** interface. This interface is used from within the runtime to make a call +** on the COM server directly when it implements the IEnumerable interface. +** +** +==========================================================================*/ +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")] + internal interface IEnumerable + { + [DispId(-4)] + System.Collections.IEnumerator GetEnumerator(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs new file mode 100644 index 0000000000..aea2017b1e --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*========================================================================== +** +** Interface: IEnumerator +** +** +** Purpose: +** This interface is redefined here since the original IEnumerator interface +** has all its methods marked as ecall's since it is a managed standard +** interface. This interface is used from within the runtime to make a call +** on the COM server directly when it implements the IEnumerator interface. +** +** +==========================================================================*/ +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")] + internal interface IEnumerator + { + bool MoveNext(); + + Object Current + { + get; + } + + void Reset(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs new file mode 100644 index 0000000000..ad4ed0b8be --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*========================================================================== +** +** Interface: IExpando +** +** +** Purpose: +** This interface is redefined here since the original IExpando interface +** has all its methods marked as ecall's since it is a managed standard +** interface. This interface is used from within the runtime to make a call +** on the COM server directly when it implements the IExpando interface. +** +** +==========================================================================*/ +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + using System.Reflection; + + [Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")] + internal interface IExpando : IReflect + { + FieldInfo AddField(String name); + PropertyInfo AddProperty(String name); + MethodInfo AddMethod(String name, Delegate method); + void RemoveMember(MemberInfo m); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs new file mode 100644 index 0000000000..caee5e7fa3 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IMoniker interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [StructLayout(LayoutKind.Sequential)] + + public struct FILETIME + { + public int dwLowDateTime; + public int dwHighDateTime; + } + + [Guid("0000000f-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IMoniker + { + // IPersist portion + void GetClassID(out Guid pClassID); + + // IPersistStream portion + [PreserveSig] + int IsDirty(); + void Load(IStream pStm); + void Save(IStream pStm, [MarshalAs(UnmanagedType.Bool)] bool fClearDirty); + void GetSizeMax(out Int64 pcbSize); + + // IMoniker portion + void BindToObject(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult); + void BindToStorage(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out Object ppvObj); + void Reduce(IBindCtx pbc, int dwReduceHowFar, ref IMoniker ppmkToLeft, out IMoniker ppmkReduced); + void ComposeWith(IMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker ppmkComposite); + void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker ppenumMoniker); + [PreserveSig] + int IsEqual(IMoniker pmkOtherMoniker); + void Hash(out int pdwHash); + [PreserveSig] + int IsRunning(IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning); + void GetTimeOfLastChange(IBindCtx pbc, IMoniker pmkToLeft, out FILETIME pFileTime); + void Inverse(out IMoniker ppmk); + void CommonPrefixWith(IMoniker pmkOther, out IMoniker ppmkPrefix); + void RelativePathTo(IMoniker pmkOther, out IMoniker ppmkRelPath); + void GetDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out String ppszDisplayName); + void ParseDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] String pszDisplayName, out int pchEaten, out IMoniker ppmkOut); + [PreserveSig] + int IsSystemMoniker(out int pdwMksys); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs new file mode 100644 index 0000000000..a9f118a354 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IPersistFile interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("0000010b-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IPersistFile + { + // IPersist portion + void GetClassID(out Guid pClassID); + + // IPersistFile portion + [PreserveSig] + int IsDirty(); + void Load([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, int dwMode); + void Save([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember); + void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] String pszFileName); + void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out String ppszFileName); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs new file mode 100644 index 0000000000..c86f961d01 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*========================================================================== +** +** Interface: IReflect +** +** +** Purpose: +** This interface is redefined here since the original IReflect interface +** has all its methods marked as ecall's since it is a managed standard +** interface. This interface is used from within the runtime to make a call +** on the COM server directly when it implements the IReflect interface. +** +** +==========================================================================*/ +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + using System.Reflection; + using CultureInfo = System.Globalization.CultureInfo; + + [Guid("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")] + internal interface IReflect + { + MethodInfo GetMethod(String name,BindingFlags bindingAttr,Binder binder, + Type[] types,ParameterModifier[] modifiers); + + MethodInfo GetMethod(String name,BindingFlags bindingAttr); + + MethodInfo[] GetMethods( + BindingFlags bindingAttr); + + FieldInfo GetField( + String name, + BindingFlags bindingAttr); + + FieldInfo[] GetFields( + BindingFlags bindingAttr); + + PropertyInfo GetProperty( + String name, + BindingFlags bindingAttr); + + PropertyInfo GetProperty( + String name, + BindingFlags bindingAttr, + Binder binder, + Type returnType, + Type[] types, + ParameterModifier[] modifiers); + + PropertyInfo[] GetProperties( + BindingFlags bindingAttr); + + MemberInfo[] GetMember( + String name, + BindingFlags bindingAttr); + + MemberInfo[] GetMembers( + BindingFlags bindingAttr); + + Object InvokeMember( + String name, + BindingFlags invokeAttr, + Binder binder, + Object target, + Object[] args, + ParameterModifier[] modifiers, + CultureInfo culture, + String[] namedParameters); + + Type UnderlyingSystemType + { + get; + } + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs new file mode 100644 index 0000000000..bebbdec70c --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IRunningObjectTable interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00000010-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IRunningObjectTable + { + int Register(int grfFlags, [MarshalAs(UnmanagedType.Interface)] Object punkObject, IMoniker pmkObjectName); + void Revoke(int dwRegister); + [PreserveSig] + int IsRunning(IMoniker pmkObjectName); + [PreserveSig] + int GetObject(IMoniker pmkObjectName, [MarshalAs(UnmanagedType.Interface)] out Object ppunkObject); + void NoteChangeTime(int dwRegister, ref FILETIME pfiletime); + [PreserveSig] + int GetTimeOfLastChange(IMoniker pmkObjectName, out FILETIME pfiletime); + void EnumRunning(out IEnumMoniker ppenumMoniker); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs new file mode 100644 index 0000000000..616ecbfa18 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: IStream interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct STATSTG + { + public String pwcsName; + public int type; + public Int64 cbSize; + public FILETIME mtime; + public FILETIME ctime; + public FILETIME atime; + public int grfMode; + public int grfLocksSupported; + public Guid clsid; + public int grfStateBits; + public int reserved; + } + + [Guid("0000000c-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IStream + { + // ISequentialStream portion + void Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] Byte[] pv, int cb, IntPtr pcbRead); + void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] pv, int cb, IntPtr pcbWritten); + + // IStream portion + void Seek(Int64 dlibMove, int dwOrigin, IntPtr plibNewPosition); + void SetSize(Int64 libNewSize); + void CopyTo(IStream pstm, Int64 cb, IntPtr pcbRead, IntPtr pcbWritten); + void Commit(int grfCommitFlags); + void Revert(); + void LockRegion(Int64 libOffset, Int64 cb, int dwLockType); + void UnlockRegion(Int64 libOffset, Int64 cb, int dwLockType); + void Stat(out STATSTG pstatstg, int grfStatFlag); + void Clone(out IStream ppstm); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs new file mode 100644 index 0000000000..f938ba91a7 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: ITypeComp interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Serializable] + public enum DESCKIND + { + DESCKIND_NONE = 0, + DESCKIND_FUNCDESC = DESCKIND_NONE + 1, + DESCKIND_VARDESC = DESCKIND_FUNCDESC + 1, + DESCKIND_TYPECOMP = DESCKIND_VARDESC + 1, + DESCKIND_IMPLICITAPPOBJ = DESCKIND_TYPECOMP + 1, + DESCKIND_MAX = DESCKIND_IMPLICITAPPOBJ + 1 + } + + [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)] + + public struct BINDPTR + { + [FieldOffset(0)] + public IntPtr lpfuncdesc; + [FieldOffset(0)] + public IntPtr lpvardesc; + [FieldOffset(0)] + public IntPtr lptcomp; + } + + [Guid("00020403-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ITypeComp + { + void Bind([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, Int16 wFlags, out ITypeInfo ppTInfo, out DESCKIND pDescKind, out BINDPTR pBindPtr); + void BindType([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, out ITypeInfo ppTInfo, out ITypeComp ppTComp); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs new file mode 100644 index 0000000000..7a12605f20 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs @@ -0,0 +1,335 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: ITypeInfo interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Serializable] + public enum TYPEKIND + { + TKIND_ENUM = 0, + TKIND_RECORD = TKIND_ENUM + 1, + TKIND_MODULE = TKIND_RECORD + 1, + TKIND_INTERFACE = TKIND_MODULE + 1, + TKIND_DISPATCH = TKIND_INTERFACE + 1, + TKIND_COCLASS = TKIND_DISPATCH + 1, + TKIND_ALIAS = TKIND_COCLASS + 1, + TKIND_UNION = TKIND_ALIAS + 1, + TKIND_MAX = TKIND_UNION + 1 + } + +[Serializable] +[Flags()] + public enum TYPEFLAGS : short + { + TYPEFLAG_FAPPOBJECT = 0x1, + TYPEFLAG_FCANCREATE = 0x2, + TYPEFLAG_FLICENSED = 0x4, + TYPEFLAG_FPREDECLID = 0x8, + TYPEFLAG_FHIDDEN = 0x10, + TYPEFLAG_FCONTROL = 0x20, + TYPEFLAG_FDUAL = 0x40, + TYPEFLAG_FNONEXTENSIBLE = 0x80, + TYPEFLAG_FOLEAUTOMATION = 0x100, + TYPEFLAG_FRESTRICTED = 0x200, + TYPEFLAG_FAGGREGATABLE = 0x400, + TYPEFLAG_FREPLACEABLE = 0x800, + TYPEFLAG_FDISPATCHABLE = 0x1000, + TYPEFLAG_FREVERSEBIND = 0x2000, + TYPEFLAG_FPROXY = 0x4000 + } + +[Serializable] +[Flags()] + public enum IMPLTYPEFLAGS + { + IMPLTYPEFLAG_FDEFAULT = 0x1, + IMPLTYPEFLAG_FSOURCE = 0x2, + IMPLTYPEFLAG_FRESTRICTED = 0x4, + IMPLTYPEFLAG_FDEFAULTVTABLE = 0x8, + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct TYPEATTR + { + // Constant used with the memid fields. + public const int MEMBER_ID_NIL = unchecked((int)0xFFFFFFFF); + + // Actual fields of the TypeAttr struct. + public Guid guid; + public Int32 lcid; + public Int32 dwReserved; + public Int32 memidConstructor; + public Int32 memidDestructor; + public IntPtr lpstrSchema; + public Int32 cbSizeInstance; + public TYPEKIND typekind; + public Int16 cFuncs; + public Int16 cVars; + public Int16 cImplTypes; + public Int16 cbSizeVft; + public Int16 cbAlignment; + public TYPEFLAGS wTypeFlags; + public Int16 wMajorVerNum; + public Int16 wMinorVerNum; + public TYPEDESC tdescAlias; + public IDLDESC idldescType; + } + + [StructLayout(LayoutKind.Sequential)] + + public struct FUNCDESC + { + public int memid; //MEMBERID memid; + public IntPtr lprgscode; // /* [size_is(cScodes)] */ SCODE RPC_FAR *lprgscode; + public IntPtr lprgelemdescParam; // /* [size_is(cParams)] */ ELEMDESC __RPC_FAR *lprgelemdescParam; + public FUNCKIND funckind; //FUNCKIND funckind; + public INVOKEKIND invkind; //INVOKEKIND invkind; + public CALLCONV callconv; //CALLCONV callconv; + public Int16 cParams; //short cParams; + public Int16 cParamsOpt; //short cParamsOpt; + public Int16 oVft; //short oVft; + public Int16 cScodes; //short cScodes; + public ELEMDESC elemdescFunc; //ELEMDESC elemdescFunc; + public Int16 wFuncFlags; //WORD wFuncFlags; + } + +[Serializable] +[Flags()] + public enum IDLFLAG : short + { + IDLFLAG_NONE = PARAMFLAG.PARAMFLAG_NONE, + IDLFLAG_FIN = PARAMFLAG.PARAMFLAG_FIN, + IDLFLAG_FOUT = PARAMFLAG.PARAMFLAG_FOUT, + IDLFLAG_FLCID = PARAMFLAG.PARAMFLAG_FLCID, + IDLFLAG_FRETVAL = PARAMFLAG.PARAMFLAG_FRETVAL + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct IDLDESC + { + public IntPtr dwReserved; + public IDLFLAG wIDLFlags; + } + +[Serializable] +[Flags()] + public enum PARAMFLAG :short + { + PARAMFLAG_NONE = 0, + PARAMFLAG_FIN = 0x1, + PARAMFLAG_FOUT = 0x2, + PARAMFLAG_FLCID = 0x4, + PARAMFLAG_FRETVAL = 0x8, + PARAMFLAG_FOPT = 0x10, + PARAMFLAG_FHASDEFAULT = 0x20, + PARAMFLAG_FHASCUSTDATA = 0x40 + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct PARAMDESC + { + public IntPtr lpVarValue; + public PARAMFLAG wParamFlags; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct TYPEDESC + { + public IntPtr lpValue; + public Int16 vt; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct ELEMDESC + { + public TYPEDESC tdesc; + + [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)] + + public struct DESCUNION + { + [FieldOffset(0)] + public IDLDESC idldesc; + [FieldOffset(0)] + public PARAMDESC paramdesc; + }; + public DESCUNION desc; + } + + [Serializable] + public enum VARKIND : int + { + VAR_PERINSTANCE = 0x0, + VAR_STATIC = 0x1, + VAR_CONST = 0x2, + VAR_DISPATCH = 0x3 + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct VARDESC + { + public int memid; + public String lpstrSchema; + + [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)] + + public struct DESCUNION + { + [FieldOffset(0)] + public int oInst; + [FieldOffset(0)] + public IntPtr lpvarValue; + }; + + public DESCUNION desc; + + public ELEMDESC elemdescVar; + public short wVarFlags; + public VARKIND varkind; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct DISPPARAMS + { + public IntPtr rgvarg; + public IntPtr rgdispidNamedArgs; + public int cArgs; + public int cNamedArgs; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + + public struct EXCEPINFO + { + public Int16 wCode; + public Int16 wReserved; + [MarshalAs(UnmanagedType.BStr)] public String bstrSource; + [MarshalAs(UnmanagedType.BStr)] public String bstrDescription; + [MarshalAs(UnmanagedType.BStr)] public String bstrHelpFile; + public int dwHelpContext; + public IntPtr pvReserved; + public IntPtr pfnDeferredFillIn; + public Int32 scode; + } + + [Serializable] + public enum FUNCKIND : int + { + FUNC_VIRTUAL = 0, + FUNC_PUREVIRTUAL = 1, + FUNC_NONVIRTUAL = 2, + FUNC_STATIC = 3, + FUNC_DISPATCH = 4 + } + +[Serializable] +[Flags] + public enum INVOKEKIND : int + { + INVOKE_FUNC = 0x1, + INVOKE_PROPERTYGET = 0x2, + INVOKE_PROPERTYPUT = 0x4, + INVOKE_PROPERTYPUTREF = 0x8 + } + + [Serializable] + public enum CALLCONV : int + { + CC_CDECL =1, + CC_MSCPASCAL=2, + CC_PASCAL =CC_MSCPASCAL, + CC_MACPASCAL=3, + CC_STDCALL =4, + CC_RESERVED =5, + CC_SYSCALL =6, + CC_MPWCDECL =7, + CC_MPWPASCAL=8, + CC_MAX =9 + } + +[Serializable] +[Flags()] + public enum FUNCFLAGS : short + { + FUNCFLAG_FRESTRICTED= 0x1, + FUNCFLAG_FSOURCE = 0x2, + FUNCFLAG_FBINDABLE = 0x4, + FUNCFLAG_FREQUESTEDIT = 0x8, + FUNCFLAG_FDISPLAYBIND = 0x10, + FUNCFLAG_FDEFAULTBIND = 0x20, + FUNCFLAG_FHIDDEN = 0x40, + FUNCFLAG_FUSESGETLASTERROR= 0x80, + FUNCFLAG_FDEFAULTCOLLELEM= 0x100, + FUNCFLAG_FUIDEFAULT = 0x200, + FUNCFLAG_FNONBROWSABLE = 0x400, + FUNCFLAG_FREPLACEABLE = 0x800, + FUNCFLAG_FIMMEDIATEBIND = 0x1000 + } + +[Serializable] +[Flags()] + public enum VARFLAGS : short + { + VARFLAG_FREADONLY =0x1, + VARFLAG_FSOURCE =0x2, + VARFLAG_FBINDABLE =0x4, + VARFLAG_FREQUESTEDIT =0x8, + VARFLAG_FDISPLAYBIND =0x10, + VARFLAG_FDEFAULTBIND =0x20, + VARFLAG_FHIDDEN =0x40, + VARFLAG_FRESTRICTED =0x80, + VARFLAG_FDEFAULTCOLLELEM =0x100, + VARFLAG_FUIDEFAULT =0x200, + VARFLAG_FNONBROWSABLE =0x400, + VARFLAG_FREPLACEABLE =0x800, + VARFLAG_FIMMEDIATEBIND =0x1000 + } + + [Guid("00020401-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ITypeInfo + { + void GetTypeAttr(out IntPtr ppTypeAttr); + void GetTypeComp(out ITypeComp ppTComp); + void GetFuncDesc(int index, out IntPtr ppFuncDesc); + void GetVarDesc(int index, out IntPtr ppVarDesc); + void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames); + void GetRefTypeOfImplType(int index, out int href); + void GetImplTypeFlags(int index, out IMPLTYPEFLAGS pImplTypeFlags); + void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId); + void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr); + void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile); + void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal); + void GetRefTypeInfo(int hRef, out ITypeInfo ppTI); + void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv); + void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj); + void GetMops(int memid, out String pBstrMops); + void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex); + [PreserveSig] + void ReleaseTypeAttr(IntPtr pTypeAttr); + [PreserveSig] + void ReleaseFuncDesc(IntPtr pFuncDesc); + [PreserveSig] + void ReleaseVarDesc(IntPtr pVarDesc); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs new file mode 100644 index 0000000000..a782b9edd6 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: ITypeInfo2 interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00020412-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ITypeInfo2 : ITypeInfo + { + new void GetTypeAttr(out IntPtr ppTypeAttr); + new void GetTypeComp(out ITypeComp ppTComp); + new void GetFuncDesc(int index, out IntPtr ppFuncDesc); + new void GetVarDesc(int index, out IntPtr ppVarDesc); + new void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames); + new void GetRefTypeOfImplType(int index, out int href); + new void GetImplTypeFlags(int index, out IMPLTYPEFLAGS pImplTypeFlags); + new void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId); + new void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr); + new void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile); + new void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal); + new void GetRefTypeInfo(int hRef, out ITypeInfo ppTI); + new void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv); + new void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj); + new void GetMops(int memid, out String pBstrMops); + new void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex); + [PreserveSig] + new void ReleaseTypeAttr(IntPtr pTypeAttr); + [PreserveSig] + new void ReleaseFuncDesc(IntPtr pFuncDesc); + [PreserveSig] + new void ReleaseVarDesc(IntPtr pVarDesc); + void GetTypeKind(out TYPEKIND pTypeKind); + void GetTypeFlags(out int pTypeFlags); + void GetFuncIndexOfMemId(int memid, INVOKEKIND invKind, out int pFuncIndex); + void GetVarIndexOfMemId(int memid, out int pVarIndex); + void GetCustData(ref Guid guid, out Object pVarVal); + void GetFuncCustData(int index, ref Guid guid, out Object pVarVal); + void GetParamCustData(int indexFunc, int indexParam, ref Guid guid, out Object pVarVal); + void GetVarCustData(int index, ref Guid guid, out Object pVarVal); + void GetImplTypeCustData(int index, ref Guid guid, out Object pVarVal); + [LCIDConversionAttribute(1)] + void GetDocumentation2(int memid, out String pbstrHelpString, out int pdwHelpStringContext, out String pbstrHelpStringDll); + void GetAllCustData(IntPtr pCustData); + void GetAllFuncCustData(int index, IntPtr pCustData); + void GetAllParamCustData(int indexFunc, int indexParam, IntPtr pCustData); + void GetAllVarCustData(int index, IntPtr pCustData); + void GetAllImplTypeCustData(int index, IntPtr pCustData); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs new file mode 100644 index 0000000000..c39b088c0b --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: ITypeLib interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Serializable] + public enum SYSKIND + { + SYS_WIN16 = 0, + SYS_WIN32 = SYS_WIN16 + 1, + SYS_MAC = SYS_WIN32 + 1, + SYS_WIN64 = SYS_MAC + 1 + } + +[Serializable] +[Flags()] + public enum LIBFLAGS : short + { + LIBFLAG_FRESTRICTED = 0x1, + LIBFLAG_FCONTROL = 0x2, + LIBFLAG_FHIDDEN = 0x4, + LIBFLAG_FHASDISKIMAGE = 0x8 + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + [Serializable] + public struct TYPELIBATTR + { + public Guid guid; + public int lcid; + public SYSKIND syskind; + public Int16 wMajorVerNum; + public Int16 wMinorVerNum; + public LIBFLAGS wLibFlags; + } + + [Guid("00020402-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ITypeLib + { + [PreserveSig] + int GetTypeInfoCount(); + void GetTypeInfo(int index, out ITypeInfo ppTI); + void GetTypeInfoType(int index, out TYPEKIND pTKind); + void GetTypeInfoOfGuid(ref Guid guid, out ITypeInfo ppTInfo); + void GetLibAttr(out IntPtr ppTLibAttr); + void GetTypeComp(out ITypeComp ppTComp); + void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile); + [return : MarshalAs(UnmanagedType.Bool)] + bool IsName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal); + void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] ITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound); + [PreserveSig] + void ReleaseTLibAttr(IntPtr pTLibAttr); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs new file mode 100644 index 0000000000..5a7d07c001 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: ITypeLib2 interface definition. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices.ComTypes +{ + using System; + + [Guid("00020411-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ITypeLib2 : ITypeLib + { + [PreserveSig] + new int GetTypeInfoCount(); + new void GetTypeInfo(int index, out ITypeInfo ppTI); + new void GetTypeInfoType(int index, out TYPEKIND pTKind); + new void GetTypeInfoOfGuid(ref Guid guid, out ITypeInfo ppTInfo); + new void GetLibAttr(out IntPtr ppTLibAttr); + new void GetTypeComp(out ITypeComp ppTComp); + new void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile); + [return : MarshalAs(UnmanagedType.Bool)] + new bool IsName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal); + new void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] ITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound); + [PreserveSig] + new void ReleaseTLibAttr(IntPtr pTLibAttr); + void GetCustData(ref Guid guid, out Object pVarVal); + [LCIDConversionAttribute(1)] + void GetDocumentation2(int index, out String pbstrHelpString, out int pdwHelpStringContext, out String pbstrHelpStringDll); + void GetLibStatistics(IntPtr pcUniqueNames, out int pcchUniqueNames); + void GetAllCustData(IntPtr pCustData); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs new file mode 100644 index 0000000000..54fd6b0cdd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs @@ -0,0 +1,275 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** +** A specially designed handle wrapper to ensure we never leak +** an OS handle. The runtime treats this class specially during +** P/Invoke marshaling and finalization. Users should write +** subclasses of CriticalHandle for each distinct handle type. +** This class is similar to SafeHandle, but lacks the ref counting +** behavior on marshaling that prevents handle recycling errors +** or security holes. This lowers the overhead of using the handle +** considerably, but leaves the onus on the caller to protect +** themselves from any recycling effects. +** +** **** NOTE **** +** +** Since there are no ref counts tracking handle usage there is +** no thread safety either. Your application must ensure that +** usages of the handle do not cross with attempts to close the +** handle (or tolerate such crossings). Normal GC mechanics will +** prevent finalization until the handle class isn't used any more, +** but explicit Close or Dispose operations may be initiated at any +** time. +** +** Similarly, multiple calls to Close or Dispose on different +** threads at the same time may cause the ReleaseHandle method to be +** called more than once. +** +** In general (and as might be inferred from the lack of handle +** recycle protection) you should be very cautious about exposing +** CriticalHandle instances directly or indirectly to untrusted users. +** At a minimum you should restrict their ability to queue multiple +** operations against a single handle at the same time or block their +** access to Close and Dispose unless you are very comfortable with the +** semantics of passing an invalid (or possibly invalidated and +** reallocated) to the unamanged routines you marshal your handle to +** (and the effects of closing such a handle while those calls are in +** progress). The runtime cannot protect you from undefined program +** behvior that might result from such scenarios. You have been warned. +** +** +===========================================================*/ + +using System; +using System.Reflection; +using System.Threading; +using System.Security.Permissions; +using System.Runtime.CompilerServices; +using System.Runtime.Versioning; +using System.Runtime.ConstrainedExecution; +using System.IO; + +/* + Problems addressed by the CriticalHandle class: + 1) Critical finalization - ensure we never leak OS resources in SQL. Done + without running truly arbitrary & unbounded amounts of managed code. + 2) Reduced graph promotion - during finalization, keep object graph small + 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race condition (HandleRef) + 4) Enforcement of the above via the type system - Don't use IntPtr anymore. + + Subclasses of CriticalHandle will implement the ReleaseHandle + abstract method used to execute any code required to free the + handle. This method will be prepared as a constrained execution + region at instance construction time (along with all the methods in + its statically determinable call graph). This implies that we won't + get any inconvenient jit allocation errors or rude thread abort + interrupts while releasing the handle but the user must still write + careful code to avoid injecting fault paths of their own (see the + CER spec for more details). In particular, any sub-methods you call + should be decorated with a reliability contract of the appropriate + level. In most cases this should be: + ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success) + Also, any P/Invoke methods should use the + SuppressUnmanagedCodeSecurity attribute to avoid a runtime security + check that can also inject failures (even if the check is guaranteed + to pass). + + Subclasses must also implement the IsInvalid property so that the + infrastructure can tell when critical finalization is actually required. + Again, this method is prepared ahead of time. It's envisioned that direct + subclasses of CriticalHandle will provide an IsInvalid implementation that suits + the general type of handle they support (null is invalid, -1 is invalid etc.) + and then these classes will be further derived for specific handle types. + + Most classes using CriticalHandle should not provide a finalizer. If they do + need to do so (ie, for flushing out file buffers, needing to write some data + back into memory, etc), then they can provide a finalizer that will be + guaranteed to run before the CriticalHandle's critical finalizer. + + Subclasses are expected to be written as follows (note that + SuppressUnmanagedCodeSecurity should always be used on any P/Invoke methods + invoked as part of ReleaseHandle, in order to switch the security check from + runtime to jit time and thus remove a possible failure path from the + invocation of the method): + + internal sealed MyCriticalHandleSubclass : CriticalHandle { + // Called by P/Invoke when returning CriticalHandles + private MyCriticalHandleSubclass() : base(IntPtr.Zero) + { + } + + // Do not provide a finalizer - CriticalHandle's critical finalizer will + // call ReleaseHandle for you. + + public override bool IsInvalid { + get { return handle == IntPtr.Zero; } + } + + [DllImport(Win32Native.KERNEL32), SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private static extern bool CloseHandle(IntPtr handle); + + override protected bool ReleaseHandle() + { + return CloseHandle(handle); + } + } + + Then elsewhere to create one of these CriticalHandles, define a method + with the following type of signature (CreateFile follows this model). + Note that when returning a CriticalHandle like this, P/Invoke will call your + classes default constructor. + + [DllImport(Win32Native.KERNEL32)] + private static extern MyCriticalHandleSubclass CreateHandle(int someState); + + */ + +namespace System.Runtime.InteropServices +{ + +// This class should not be serializable - it's a handle. We require unmanaged +// code permission to subclass CriticalHandle to prevent people from writing a +// subclass and suddenly being able to run arbitrary native code with the +// same signature as CloseHandle. This is technically a little redundant, but +// we'll do this to ensure we've cut off all attack vectors. Similarly, all +// methods have a link demand to ensure untrusted code cannot directly edit +// or alter a handle. +[System.Security.SecurityCritical] // auto-generated_required +#if !FEATURE_CORECLR +[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)] +#endif +public abstract class CriticalHandle : CriticalFinalizerObject, IDisposable +{ + // ! Do not add or rearrange fields as the EE depends on this layout. + //------------------------------------------------------------------ +#if DEBUG + private String _stackTrace; // Where we allocated this CriticalHandle. +#endif + protected IntPtr handle; // This must be protected so derived classes can use out params. + private bool _isClosed; // Set by SetHandleAsInvalid or Close/Dispose/finalization. + + // Creates a CriticalHandle class. Users must then set the Handle property or allow P/Invoke marshaling to set it implicitly. + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected CriticalHandle(IntPtr invalidHandleValue) + { + handle = invalidHandleValue; + _isClosed = false; + +#if DEBUG + if (BCLDebug.SafeHandleStackTracesEnabled) + _stackTrace = Environment.GetStackTrace(null, false); + else + _stackTrace = "For a stack trace showing who allocated this CriticalHandle, set SafeHandleStackTraces to 1 and rerun your app."; +#endif + } + +#if FEATURE_CORECLR + // Adding an empty default constructor for annotation purposes + private CriticalHandle(){} +#endif + + [System.Security.SecuritySafeCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + ~CriticalHandle() + { + Dispose(false); + } + + [System.Security.SecurityCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private void Cleanup() + { + if (IsClosed) + return; + _isClosed = true; + + if (IsInvalid) + return; + + // Save last error from P/Invoke in case the implementation of + // ReleaseHandle trashes it (important because this ReleaseHandle could + // occur implicitly as part of unmarshaling another P/Invoke). + int lastError = Marshal.GetLastWin32Error(); + + if (!ReleaseHandle()) + FireCustomerDebugProbe(); + + Marshal.SetLastWin32Error(lastError); + + GC.SuppressFinalize(this); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private extern void FireCustomerDebugProbe(); + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + protected void SetHandle(IntPtr handle) { + this.handle = handle; + } + + // Returns whether the handle has been explicitly marked as closed + // (Close/Dispose) or invalid (SetHandleAsInvalid). + public bool IsClosed { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + get { return _isClosed; } + } + + // Returns whether the handle looks like an invalid value (i.e. matches one + // of the handle's designated illegal values). CriticalHandle itself doesn't + // know what an invalid handle looks like, so this method is abstract and + // must be provided by a derived type. + public abstract bool IsInvalid { + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + get; + } + + [System.Security.SecurityCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public void Close() { + Dispose(true); + } + + [System.Security.SecuritySafeCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public void Dispose() + { + Dispose(true); + } + + [System.Security.SecurityCritical] // auto-generated + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + protected virtual void Dispose(bool disposing) + { + Cleanup(); + } + + // This should only be called for cases when you know for a fact that + // your handle is invalid and you want to record that information. + // An example is calling a syscall and getting back ERROR_INVALID_HANDLE. + // This method will normally leak handles! + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public void SetHandleAsInvalid() + { + _isClosed = true; + GC.SuppressFinalize(this); + } + + // Implement this abstract method in your derived class to specify how to + // free the handle. Be careful not write any code that's subject to faults + // in this method (the runtime will prepare the infrastructure for you so + // that no jit allocations etc. will occur, but don't allocate memory unless + // you can deal with the failure and still free the handle). + // The boolean returned should be true for success and false if a + // catastrophic error occurred and you wish to trigger a diagnostic for + // debugging purposes (the SafeHandleCriticalFailure MDA). + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + protected abstract bool ReleaseHandle(); +} + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs new file mode 100644 index 0000000000..1f7a9f18bf --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Wrapper that is converted to a variant with VT_CURRENCY. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class CurrencyWrapper + { + public CurrencyWrapper(Decimal obj) + { + m_WrappedObject = obj; + } + + public CurrencyWrapper(Object obj) + { + if (!(obj is Decimal)) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal"), "obj"); + m_WrappedObject = (Decimal)obj; + } + + public Decimal WrappedObject + { + get + { + return m_WrappedObject; + } + } + + private Decimal m_WrappedObject; + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs new file mode 100644 index 0000000000..1fc72f74c8 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Wrapper that is converted to a variant with VT_DISPATCH. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Security; + using System.Security.Permissions; + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class DispatchWrapper + { + [System.Security.SecuritySafeCritical] // auto-generated +#pragma warning disable 618 + [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)] +#pragma warning restore 618 + public DispatchWrapper(Object obj) + { + if (obj != null) + { + // Make sure this guy has an IDispatch + IntPtr pdisp = Marshal.GetIDispatchForObject(obj); + + // If we got here without throwing an exception, the QI for IDispatch succeeded. + Marshal.Release(pdisp); + } + m_WrappedObject = obj; + } + + public Object WrappedObject + { + get + { + return m_WrappedObject; + } + } + + private Object m_WrappedObject; + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs new file mode 100644 index 0000000000..d63d69cabd --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Wrapper that is converted to a variant with VT_ERROR. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Security.Permissions; + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class ErrorWrapper + { + public ErrorWrapper(int errorCode) + { + m_ErrorCode = errorCode; + } + + public ErrorWrapper(Object errorCode) + { + if (!(errorCode is int)) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt32"), "errorCode"); + m_ErrorCode = (int)errorCode; + } + + [System.Security.SecuritySafeCritical] // auto-generated +#pragma warning disable 618 + [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] +#pragma warning restore 618 + public ErrorWrapper(Exception e) + { + m_ErrorCode = Marshal.GetHRForException(e); + } + + public int ErrorCode + { + get + { + return m_ErrorCode; + } + } + + private int m_ErrorCode; + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs b/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs new file mode 100644 index 0000000000..62b65d1aff --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// IExpando is an interface which allows Objects implemeningt this interface +// support the ability to modify the object by adding and removing members, +// represented by MemberInfo objects. +// +// +// The IExpando Interface. +namespace System.Runtime.InteropServices.Expando { + + using System; + using System.Reflection; + + [Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")] +[System.Runtime.InteropServices.ComVisible(true)] + public interface IExpando : IReflect + { + // Add a new Field to the reflection object. The field has + // name as its name. + FieldInfo AddField(String name); + + // Add a new Property to the reflection object. The property has + // name as its name. + PropertyInfo AddProperty(String name); + + // Add a new Method to the reflection object. The method has + // name as its name and method is a delegate + // to the method. + MethodInfo AddMethod(String name, Delegate method); + + // Removes the specified member. + void RemoveMember(MemberInfo m); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs new file mode 100644 index 0000000000..62718de757 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Methods used to customize the creation of managed objects that +** extend from unmanaged objects. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System.Runtime.InteropServices; + using System.Runtime.Remoting; + using System.Runtime.CompilerServices; + using System.Runtime.Versioning; + + using System; +[System.Runtime.InteropServices.ComVisible(true)] + public sealed class ExtensibleClassFactory + { + + // Prevent instantiation. + private ExtensibleClassFactory() {} + + // Register a delegate that will be called whenever an instance of a managed + // type that extends from an unmanaged type needs to allocate the aggregated + // unmanaged object. This delegate is expected to allocate and aggregate the + // unmanaged object and is called in place of a CoCreateInstance. This + // routine must be called in the context of the static initializer for the + // class for which the callbacks will be made. + // It is not legal to register this callback from a class that has any + // parents that have already registered a callback. + [System.Security.SecuritySafeCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void RegisterObjectCreationCallback(ObjectCreationDelegate callback); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs new file mode 100644 index 0000000000..417cf94bd4 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Exception base class for all errors from Interop or Structured +** Exception Handling code. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Globalization; + using System.Runtime.Serialization; + // Base exception for COM Interop errors &; Structured Exception Handler + // exceptions. + // + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public class ExternalException : SystemException { + public ExternalException() + : base(Environment.GetResourceString("Arg_ExternalException")) { + SetErrorCode(__HResults.E_FAIL); + } + + public ExternalException(String message) + : base(message) { + SetErrorCode(__HResults.E_FAIL); + } + + public ExternalException(String message, Exception inner) + : base(message, inner) { + SetErrorCode(__HResults.E_FAIL); + } + + public ExternalException(String message,int errorCode) + : base(message) { + SetErrorCode(errorCode); + } + + protected ExternalException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + + public virtual int ErrorCode { + get { + return HResult; + } + } + +#if !FEATURE_CORECLR // Breaks the subset-of-Orcas property + public override String ToString() { + String message = Message; + String s; + String _className = GetType().ToString(); + s = _className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")"; + + if (!(String.IsNullOrEmpty(message))) { + s = s + ": " + message; + } + + Exception _innerException = InnerException; + + if (_innerException!=null) { + s = s + " ---> " + _innerException.ToString(); + } + + + if (StackTrace != null) + s += Environment.NewLine + StackTrace; + + return s; + } +#endif // !FEATURE_CORECLR + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs new file mode 100644 index 0000000000..304f369879 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if MDA_SUPPORTED + +namespace System.Runtime.InteropServices +{ + using System; + using System.Collections.Generic; + using System.Threading; + + using ObjectHandle = IntPtr; + using GCHandleCookie = IntPtr; + + // Internal class used to map a GCHandle to an IntPtr. Instead of handing out the underlying CLR + // handle, we now hand out a cookie that can later be converted back to the CLR handle it + // is associated with. + + // NOTE: + // this implementation uses a single lock between FindOrAddHandle and RemoveHandleIfPresent which + // could create some scalability issues when this MDA is turned on. if this is affecting perf + // then additional tuning work will be required. + + internal class GCHandleCookieTable + { + private const int InitialHandleCount = 10; + private const int MaxListSize = 0xFFFFFF; + private const uint CookieMaskIndex = 0x00FFFFFF; + private const uint CookieMaskSentinal = 0xFF000000; + + internal GCHandleCookieTable() + { + m_HandleList = new ObjectHandle[InitialHandleCount]; + m_CycleCounts = new byte[InitialHandleCount]; + m_HandleToCookieMap = new Dictionary<ObjectHandle, GCHandleCookie>(InitialHandleCount); + m_syncObject = new object(); + + for (int i = 0; i < InitialHandleCount; i++) + { + m_HandleList[i] = ObjectHandle.Zero; + m_CycleCounts[i] = 0; + } + } + + // Retrieve a cookie for the passed in handle. If no cookie has yet been allocated for + // this handle, one will be created. This method is thread safe. + internal GCHandleCookie FindOrAddHandle(ObjectHandle handle) + { + // Don't accept a null object handle + if (handle == ObjectHandle.Zero) + return GCHandleCookie.Zero; + + GCHandleCookie cookie = GCHandleCookie.Zero; + + lock (m_syncObject) + { + // First see if we already have a cookie for this handle. + if (m_HandleToCookieMap.ContainsKey(handle)) + return m_HandleToCookieMap[handle]; + + if ((m_FreeIndex < m_HandleList.Length) && (Volatile.Read(ref m_HandleList[m_FreeIndex]) == ObjectHandle.Zero)) + { + Volatile.Write(ref m_HandleList[m_FreeIndex], handle); + cookie = GetCookieFromData((uint)m_FreeIndex, m_CycleCounts[m_FreeIndex]); + + // Set our next guess just one higher as this index is now in use. + // it's ok if this sets m_FreeIndex > m_HandleList.Length as this condition is + // checked at the beginning of the if statement. + ++m_FreeIndex; + } + else + { + for (m_FreeIndex = 0; m_FreeIndex < MaxListSize; ++m_FreeIndex) + { + if (m_HandleList[m_FreeIndex] == ObjectHandle.Zero) + { + Volatile.Write(ref m_HandleList[m_FreeIndex], handle); + cookie = GetCookieFromData((uint)m_FreeIndex, m_CycleCounts[m_FreeIndex]); + + // this will be our next guess for a free index. + // it's ok if this sets m_FreeIndex > m_HandleList.Length + // since we check for this condition in the if statement. + ++m_FreeIndex; + break; + } + + if (m_FreeIndex + 1 == m_HandleList.Length) + GrowArrays(); + } + } + + if (cookie == GCHandleCookie.Zero) + throw new OutOfMemoryException(Environment.GetResourceString("OutOfMemory_GCHandleMDA")); + + // This handle hasn't been added to the map yet so add it. + m_HandleToCookieMap.Add(handle, cookie); + } + + return cookie; + } + + // Get a handle. + internal ObjectHandle GetHandle(GCHandleCookie cookie) + { + ObjectHandle oh = ObjectHandle.Zero; + + if (!ValidateCookie(cookie)) + return ObjectHandle.Zero; + + oh = Volatile.Read(ref m_HandleList[GetIndexFromCookie(cookie)]); + + return oh; + } + + // Remove the handle from the cookie table if it is present. + // + internal void RemoveHandleIfPresent(ObjectHandle handle) + { + if (handle == ObjectHandle.Zero) + return; + + lock (m_syncObject) + { + if (m_HandleToCookieMap.ContainsKey(handle)) + { + GCHandleCookie cookie = m_HandleToCookieMap[handle]; + + // Remove it from the array first + if (!ValidateCookie(cookie)) + return; + + int index = GetIndexFromCookie(cookie); + + m_CycleCounts[index]++; + Volatile.Write(ref m_HandleList[index], ObjectHandle.Zero); + + // Remove it from the hashtable last + m_HandleToCookieMap.Remove(handle); + + // Update our guess + m_FreeIndex = index; + } + } + } + + private bool ValidateCookie(GCHandleCookie cookie) + { + int index; + byte xorData; + + GetDataFromCookie(cookie, out index, out xorData); + + // Validate the index + if (index >= MaxListSize) + return false; + + if (index >= m_HandleList.Length) + return false; + + if (Volatile.Read(ref m_HandleList[index]) == ObjectHandle.Zero) + return false; + + // Validate the xorData byte (this contains the cycle count and appdomain id). + byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF); + byte goodData = (byte)(Volatile.Read(ref m_CycleCounts[index]) ^ ADID); + if (xorData != goodData) + return false; + + return true; + } + + // Double the size of our arrays - must be called with the lock taken. + private void GrowArrays() + { + int CurrLength = m_HandleList.Length; + + ObjectHandle[] newHandleList = new ObjectHandle[CurrLength * 2]; + byte[] newCycleCounts = new byte[CurrLength * 2]; + + Array.Copy(m_HandleList, newHandleList, CurrLength); + Array.Copy(m_CycleCounts, newCycleCounts, CurrLength); + + m_HandleList = newHandleList; + m_CycleCounts = newCycleCounts; + } + + // Generate a cookie based on the index, cyclecount, and current domain id. + private GCHandleCookie GetCookieFromData(uint index, byte cycleCount) + { + byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF); + return (GCHandleCookie)(((cycleCount ^ ADID) << 24) + index + 1); + } + + // Break down the cookie into its parts + private void GetDataFromCookie(GCHandleCookie cookie, out int index, out byte xorData) + { + uint intCookie = (uint)cookie; + index = (int)(intCookie & CookieMaskIndex) - 1; + xorData = (byte)((intCookie & CookieMaskSentinal) >> 24); + } + + // Just get the index from the cookie + private int GetIndexFromCookie(GCHandleCookie cookie) + { + uint intCookie = (uint)cookie; + return (int)(intCookie & CookieMaskIndex) - 1; + } + + private Dictionary<ObjectHandle, GCHandleCookie> m_HandleToCookieMap; + private volatile ObjectHandle[] m_HandleList; + private volatile byte[] m_CycleCounts; + private int m_FreeIndex; + private readonly object m_syncObject; + } +} + +#endif + diff --git a/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs new file mode 100644 index 0000000000..58fea97cb8 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs @@ -0,0 +1,330 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.InteropServices +{ + using System; + using System.Security.Permissions; + using System.Runtime.CompilerServices; + using System.Threading; + using System.Runtime.Versioning; + using System.Diagnostics.Contracts; + + // These are the types of handles used by the EE. + // IMPORTANT: These must match the definitions in ObjectHandle.h in the EE. + // IMPORTANT: If new values are added to the enum the GCHandle::MaxHandleType + // constant must be updated. + [Serializable] + [System.Runtime.InteropServices.ComVisible(true)] + public enum GCHandleType + { + Weak = 0, + WeakTrackResurrection = 1, + Normal = 2, + Pinned = 3 + } + + // This class allows you to create an opaque, GC handle to any + // COM+ object. A GC handle is used when an object reference must be + // reachable from unmanaged memory. There are 3 kinds of roots: + // Normal - keeps the object from being collected. + // Weak - allows object to be collected and handle contents will be zeroed. + // Weak references are zeroed before the finalizer runs, so if the + // object is resurrected in the finalizer the weak reference is + // still zeroed. + // WeakTrackResurrection - Same as weak, but stays until after object is + // really gone. + // Pinned - same as normal, but allows the address of the actual object + // to be taken. + // + + [StructLayout(LayoutKind.Sequential)] + [System.Runtime.InteropServices.ComVisible(true)] + public struct GCHandle + { + // IMPORTANT: This must be kept in sync with the GCHandleType enum. + private const GCHandleType MaxHandleType = GCHandleType.Pinned; + +#if MDA_SUPPORTED + [System.Security.SecuritySafeCritical] // auto-generated + static GCHandle() + { + s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled(); + if (s_probeIsActive) + s_cookieTable = new GCHandleCookieTable(); + } +#endif + + // Allocate a handle storing the object and the type. + [System.Security.SecurityCritical] // auto-generated + internal GCHandle(Object value, GCHandleType type) + { + // Make sure the type parameter is within the valid range for the enum. + if ((uint)type > (uint)MaxHandleType) + throw new ArgumentOutOfRangeException("type", Environment.GetResourceString("ArgumentOutOfRange_Enum")); + Contract.EndContractBlock(); + + m_handle = InternalAlloc(value, type); + + // Record if the handle is pinned. + if (type == GCHandleType.Pinned) + SetIsPinned(); + } + + // Used in the conversion functions below. + [System.Security.SecurityCritical] // auto-generated + internal GCHandle(IntPtr handle) + { + InternalCheckDomain(handle); + m_handle = handle; + } + + // Creates a new GC handle for an object. + // + // value - The object that the GC handle is created for. + // type - The type of GC handle to create. + // + // returns a new GC handle that protects the object. + [System.Security.SecurityCritical] // auto-generated_required + public static GCHandle Alloc(Object value) + { + return new GCHandle(value, GCHandleType.Normal); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static GCHandle Alloc(Object value, GCHandleType type) + { + return new GCHandle(value, type); + } + + + // Frees a GC handle. + [System.Security.SecurityCritical] // auto-generated_required + public void Free() + { + // Copy the handle instance member to a local variable. This is required to prevent + // race conditions releasing the handle. + IntPtr handle = m_handle; + + // Free the handle if it hasn't already been freed. + if (handle != IntPtr.Zero && Interlocked.CompareExchange(ref m_handle, IntPtr.Zero, handle) == handle) + { +#if MDA_SUPPORTED + // If this handle was passed out to unmanaged code, we need to remove it + // from the cookie table. + // NOTE: the entry in the cookie table must be released before the + // internal handle is freed to prevent a race with reusing GC handles. + if (s_probeIsActive) + s_cookieTable.RemoveHandleIfPresent(handle); +#endif + +#if BIT64 + InternalFree((IntPtr)(((long)handle) & ~1L)); +#else // BIT64 (32) + InternalFree((IntPtr)(((int)handle) & ~1)); +#endif + } + else + { + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); + } + } + + // Target property - allows getting / updating of the handle's referent. + public Object Target + { + [System.Security.SecurityCritical] // auto-generated_required + get + { + // Check if the handle was never initialized or was freed. + if (m_handle == IntPtr.Zero) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); + + return InternalGet(GetHandleValue()); + } + + [System.Security.SecurityCritical] // auto-generated_required + set + { + // Check if the handle was never initialized or was freed. + if (m_handle == IntPtr.Zero) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); + + InternalSet(GetHandleValue(), value, IsPinned()); + } + } + + // Retrieve the address of an object in a Pinned handle. This throws + // an exception if the handle is any type other than Pinned. + [System.Security.SecurityCritical] // auto-generated_required + public IntPtr AddrOfPinnedObject() + { + // Check if the handle was not a pinned handle. + if (!IsPinned()) + { + // Check if the handle was never initialized for was freed. + if (m_handle == IntPtr.Zero) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); + + // You can only get the address of pinned handles. + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned")); + } + + // Get the address. + return InternalAddrOfPinnedObject(GetHandleValue()); + } + + // Determine whether this handle has been allocated or not. + public bool IsAllocated + { + get + { + return m_handle != IntPtr.Zero; + } + } + + // Used to create a GCHandle from an int. This is intended to + // be used with the reverse conversion. + [System.Security.SecurityCritical] // auto-generated_required + public static explicit operator GCHandle(IntPtr value) + { + return FromIntPtr(value); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static GCHandle FromIntPtr(IntPtr value) + { + if (value == IntPtr.Zero) + throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); + Contract.EndContractBlock(); + + IntPtr handle = value; + +#if MDA_SUPPORTED + if (s_probeIsActive) + { + // Make sure this cookie matches up with a GCHandle we've passed out a cookie for. + handle = s_cookieTable.GetHandle(value); + if (IntPtr.Zero == handle) + { + // Fire an MDA if we were unable to retrieve the GCHandle. + Mda.FireInvalidGCHandleCookieProbe(value); + return new GCHandle(IntPtr.Zero); + } + } +#endif + + return new GCHandle(handle); + } + + // Used to get the internal integer representation of the handle out. + public static explicit operator IntPtr(GCHandle value) + { + return ToIntPtr(value); + } + + public static IntPtr ToIntPtr(GCHandle value) + { +#if MDA_SUPPORTED + if (s_probeIsActive) + { + // Remember that we passed this GCHandle out by storing the cookie we returned so we + // can later validate. + return s_cookieTable.FindOrAddHandle(value.m_handle); + } +#endif + return value.m_handle; + } + + public override int GetHashCode() + { + return m_handle.GetHashCode(); + } + + public override bool Equals(Object o) + { + GCHandle hnd; + + // Check that o is a GCHandle first + if(o == null || !(o is GCHandle)) + return false; + else + hnd = (GCHandle) o; + + return m_handle == hnd.m_handle; + } + + public static bool operator ==(GCHandle a, GCHandle b) + { + return a.m_handle == b.m_handle; + } + + public static bool operator !=(GCHandle a, GCHandle b) + { + return a.m_handle != b.m_handle; + } + + internal IntPtr GetHandleValue() + { +#if BIT64 + return new IntPtr(((long)m_handle) & ~1L); +#else // !BIT64 (32) + return new IntPtr(((int)m_handle) & ~1); +#endif + } + + internal bool IsPinned() + { +#if BIT64 + return (((long)m_handle) & 1) != 0; +#else // !BIT64 (32) + return (((int)m_handle) & 1) != 0; +#endif + } + + internal void SetIsPinned() + { +#if BIT64 + m_handle = new IntPtr(((long)m_handle) | 1L); +#else // !BIT64 (32) + m_handle = new IntPtr(((int)m_handle) | 1); +#endif + } + + // Internal native calls that this implementation uses. + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr InternalAlloc(Object value, GCHandleType type); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InternalFree(IntPtr handle); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern Object InternalGet(IntPtr handle); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern Object InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InternalCheckDomain(IntPtr handle); + [System.Security.SecurityCritical] // auto-generated + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern GCHandleType InternalGetHandleType(IntPtr handle); + + // The actual integer handle value that the EE uses internally. + private IntPtr m_handle; + +#if MDA_SUPPORTED + // The GCHandle cookie table. + static private volatile GCHandleCookieTable s_cookieTable = null; + static private volatile bool s_probeIsActive = false; +#endif + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs b/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs new file mode 100644 index 0000000000..d76750fdd7 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.InteropServices +{ + + using System; + + [System.Runtime.InteropServices.ComVisible(true)] + public struct HandleRef + { + + // ! Do not add or rearrange fields as the EE depends on this layout. + //------------------------------------------------------------------ + internal Object m_wrapper; + internal IntPtr m_handle; + //------------------------------------------------------------------ + + + public HandleRef(Object wrapper, IntPtr handle) + { + m_wrapper = wrapper; + m_handle = handle; + } + + public Object Wrapper { + get { + return m_wrapper; + } + } + + public IntPtr Handle { + get { + return m_handle; + } + } + + + public static explicit operator IntPtr(HandleRef value) + { + return value.m_handle; + } + + public static IntPtr ToIntPtr(HandleRef value) + { + return value.m_handle; + } + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs new file mode 100644 index 0000000000..00abf7b3bf --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: This the base interface that custom adapters can chose to implement +** when they want to expose the underlying object. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System; + +[System.Runtime.InteropServices.ComVisible(true)] + public interface ICustomAdapter + { + [return:MarshalAs(UnmanagedType.IUnknown)] Object GetUnderlyingObject(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs new file mode 100644 index 0000000000..33d2556bd0 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices { + + using System; + +[System.Runtime.InteropServices.ComVisible(true)] + public interface ICustomFactory + { + MarshalByRefObject CreateInstance(Type serverType); + } + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs new file mode 100644 index 0000000000..4db4acceeb --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: This the base interface that must be implemented by all custom +** marshalers. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System; + +[System.Runtime.InteropServices.ComVisible(true)] + public interface ICustomMarshaler + { + Object MarshalNativeToManaged( IntPtr pNativeData ); + + IntPtr MarshalManagedToNative( Object ManagedObj ); + + void CleanUpNativeData( IntPtr pNativeData ); + + void CleanUpManagedData( Object ManagedObj ); + + int GetNativeDataSize(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs new file mode 100644 index 0000000000..61688b90b4 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: This the interface that be implemented by class that want to +** customize the behavior of QueryInterface. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System; + + //==================================================================== + // The enum of the return value of IQuerable.GetInterface + //==================================================================== + [Serializable] + [System.Runtime.InteropServices.ComVisible(false)] + public enum CustomQueryInterfaceResult + { + Handled = 0, + NotHandled = 1, + Failed = 2, + } + + //==================================================================== + // The interface for customizing IQueryInterface + //==================================================================== + [System.Runtime.InteropServices.ComVisible(false)] + public interface ICustomQueryInterface + { + [System.Security.SecurityCritical] + CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IException.cs b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs new file mode 100644 index 0000000000..2da0a564a2 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** Interface: _Exception +** +** +** Purpose: COM backwards compatibility with v1 Exception +** object layout. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + using System; + using System.Reflection; + using System.Runtime.Serialization; + using System.Security.Permissions; + + [GuidAttribute("b36b5c63-42ef-38bc-a07e-0b34c98f164a")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)] + [CLSCompliant(false)] +[System.Runtime.InteropServices.ComVisible(true)] + public interface _Exception + { +#if !FEATURE_CORECLR + // This contains all of our V1 Exception class's members. + + // From Object + String ToString(); + bool Equals (Object obj); + int GetHashCode (); + Type GetType (); + + // From V1's Exception class + String Message { + get; + } + + Exception GetBaseException(); + + String StackTrace { + get; + } + + String HelpLink { + get; + set; + } + + String Source { + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + get; + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + set; + } + [System.Security.SecurityCritical] // auto-generated_required + void GetObjectData(SerializationInfo info, StreamingContext context); +#endif + + // + // This method is intentionally included in CoreCLR to make Exception.get_InnerException "newslot virtual final". + // Some phone apps include MEF from desktop Silverlight. MEF's ComposablePartException depends on implicit interface + // implementations of get_InnerException to be provided by the base class. It works only if Exception.get_InnerException + // is virtual. + // + Exception InnerException { + get; + } + +#if !FEATURE_CORECLR + MethodBase TargetSite { + get; + } +#endif + } + +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs new file mode 100644 index 0000000000..ae330e8652 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: This interface provides services for registering and unregistering +** a managed server for use by COM. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Reflection; + using System.Security; + using System.Security.Permissions; + + [Flags()] +[System.Runtime.InteropServices.ComVisible(true)] + public enum AssemblyRegistrationFlags + { + None = 0x00000000, + SetCodeBase = 0x00000001, + } + + [Guid("CCBD682C-73A5-4568-B8B0-C7007E11ABA2")] +[System.Runtime.InteropServices.ComVisible(true)] + public interface IRegistrationServices + { + [System.Security.SecurityCritical] // auto-generated_required + bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags); + + [System.Security.SecurityCritical] // auto-generated_required + bool UnregisterAssembly(Assembly assembly); + + [System.Security.SecurityCritical] // auto-generated_required + Type[] GetRegistrableTypesInAssembly(Assembly assembly); + + [System.Security.SecurityCritical] // auto-generated_required + String GetProgIdForType(Type type); + + [System.Security.SecurityCritical] // auto-generated_required + void RegisterTypeForComClients(Type type, ref Guid g); + + Guid GetManagedCategoryGuid(); + + [System.Security.SecurityCritical] // auto-generated_required + bool TypeRequiresRegistration(Type type); + + bool TypeRepresentsComType(Type type); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs b/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs new file mode 100644 index 0000000000..a7b6889c55 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: Methods used to convert a TypeLib to metadata and vice versa. +** +** +=============================================================================*/ + +// *************************************************************************** +// *** Note: The following definitions must remain synchronized with the IDL +// *** in src/inc/TlbImpExp.idl. +// *************************************************************************** + +namespace System.Runtime.InteropServices { + + using System; + using System.Reflection; + using System.Reflection.Emit; + +[Serializable] +[Flags()] +[System.Runtime.InteropServices.ComVisible(true)] + public enum TypeLibImporterFlags + { + None = 0x00000000, + PrimaryInteropAssembly = 0x00000001, + UnsafeInterfaces = 0x00000002, + SafeArrayAsSystemArray = 0x00000004, + TransformDispRetVals = 0x00000008, + PreventClassMembers = 0x00000010, + SerializableValueClasses = 0x00000020, + ImportAsX86 = 0x00000100, + ImportAsX64 = 0x00000200, + ImportAsItanium = 0x00000400, + ImportAsAgnostic = 0x00000800, + ReflectionOnlyLoading = 0x00001000, + NoDefineVersionResource = 0x00002000, + ImportAsArm = 0x00004000, + } + +[Serializable] +[Flags()] +[System.Runtime.InteropServices.ComVisible(true)] + public enum TypeLibExporterFlags + { + None = 0x00000000, + OnlyReferenceRegistered = 0x00000001, + CallerResolvedReferences = 0x00000002, + OldNames = 0x00000004, + ExportAs32Bit = 0x00000010, + ExportAs64Bit = 0x00000020, + } + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum ImporterEventKind + { + NOTIF_TYPECONVERTED = 0, + NOTIF_CONVERTWARNING = 1, + ERROR_REFTOINVALIDTYPELIB = 2, + } + + [Serializable] +[System.Runtime.InteropServices.ComVisible(true)] + public enum ExporterEventKind + { + NOTIF_TYPECONVERTED = 0, + NOTIF_CONVERTWARNING = 1, + ERROR_REFTOINVALIDASSEMBLY = 2 + } + + [GuidAttribute("F1C3BF76-C3E4-11d3-88E7-00902754C43A")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +[System.Runtime.InteropServices.ComVisible(true)] + public interface ITypeLibImporterNotifySink + { + void ReportEvent( + ImporterEventKind eventKind, + int eventCode, + String eventMsg); + Assembly ResolveRef( + [MarshalAs(UnmanagedType.Interface)] Object typeLib); + } + + [GuidAttribute("F1C3BF77-C3E4-11d3-88E7-00902754C43A")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +[System.Runtime.InteropServices.ComVisible(true)] + public interface ITypeLibExporterNotifySink + { + void ReportEvent( + ExporterEventKind eventKind, + int eventCode, + String eventMsg); + + [return : MarshalAs(UnmanagedType.Interface)] + Object ResolveRef( + Assembly assembly); + } + + [GuidAttribute("F1C3BF78-C3E4-11d3-88E7-00902754C43A")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +[System.Runtime.InteropServices.ComVisible(true)] + public interface ITypeLibConverter + { + AssemblyBuilder ConvertTypeLibToAssembly( + [MarshalAs(UnmanagedType.Interface)] Object typeLib, + String asmFileName, + TypeLibImporterFlags flags, + ITypeLibImporterNotifySink notifySink, + byte[] publicKey, + StrongNameKeyPair keyPair, + String asmNamespace, + Version asmVersion); + + [return : MarshalAs(UnmanagedType.Interface)] + Object ConvertAssemblyToTypeLib( + Assembly assembly, + String typeLibName, + TypeLibExporterFlags flags, + ITypeLibExporterNotifySink notifySink); + + bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase); + + AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib, + String asmFileName, + int flags, + ITypeLibImporterNotifySink notifySink, + byte[] publicKey, + StrongNameKeyPair keyPair, + bool unsafeInterfaces); + } + + [GuidAttribute("FA1F3615-ACB9-486d-9EAC-1BEF87E36B09")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] +[System.Runtime.InteropServices.ComVisible(true)] + public interface ITypeLibExporterNameProvider + { + [return : MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)] + String[] GetNames(); + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs b/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs new file mode 100644 index 0000000000..ac8258b872 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** Purpose: This exception is thrown when an invalid COM object is used. This +** happens when a the __ComObject type is used directly without +** having a backing class factory. +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Runtime.Serialization; + + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public class InvalidComObjectException : SystemException { + public InvalidComObjectException() + : base(Environment.GetResourceString("Arg_InvalidComObjectException")) { + SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT); + } + + public InvalidComObjectException(String message) + : base(message) { + SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT); + } + + public InvalidComObjectException(String message, Exception inner) + : base(message, inner) { + SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT); + } + + protected InvalidComObjectException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs b/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs new file mode 100644 index 0000000000..60c9aa67b4 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** Purpose: The type of an OLE variant that was passed into the runtime is +** invalid. +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Runtime.Serialization; + + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public class InvalidOleVariantTypeException : SystemException { + public InvalidOleVariantTypeException() + : base(Environment.GetResourceString("Arg_InvalidOleVariantTypeException")) { + SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE); + } + + public InvalidOleVariantTypeException(String message) + : base(message) { + SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE); + } + + public InvalidOleVariantTypeException(String message, Exception inner) + : base(message, inner) { + SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE); + } + + protected InvalidOleVariantTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs b/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs new file mode 100644 index 0000000000..231779872e --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +namespace System.Runtime.InteropServices { + using System; + // Used in the StructLayoutAttribute class + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public enum LayoutKind + { + Sequential = 0, // 0x00000008, + Explicit = 2, // 0x00000010, + Auto = 3, // 0x00000000, + } +} diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs new file mode 100644 index 0000000000..86e88306f0 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs @@ -0,0 +1,2806 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** +** Purpose: This class contains methods that are mainly used to marshal +** between unmanaged and managed types. +** +** +=============================================================================*/ + +namespace System.Runtime.InteropServices +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using System.Reflection.Emit; + using System.Security; + using System.Security.Permissions; + using System.Text; + using System.Threading; + using System.Runtime.Remoting; + using System.Runtime.CompilerServices; + using System.Globalization; + using System.Runtime.ConstrainedExecution; + using System.Runtime.Versioning; + using Win32Native = Microsoft.Win32.Win32Native; + using Microsoft.Win32.SafeHandles; + using System.Diagnostics.Contracts; + using System.Runtime.InteropServices.ComTypes; + + [Serializable] + public enum CustomQueryInterfaceMode + { + Ignore = 0, + Allow = 1 + } + + //======================================================================== + // All public methods, including PInvoke, are protected with linkchecks. + // Remove the default demands for all PInvoke methods with this global + // declaration on the class. + //======================================================================== + + #if FEATURE_CORECLR + [System.Security.SecurityCritical] // auto-generated + #endif + public static partial class Marshal + { + //==================================================================== + // Defines used inside the Marshal class. + //==================================================================== + private const int LMEM_FIXED = 0; + private const int LMEM_MOVEABLE = 2; +#if !FEATURE_PAL + private const long HIWORDMASK = unchecked((long)0xffffffffffff0000L); +#endif //!FEATURE_PAL +#if FEATURE_COMINTEROP + private static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); +#endif //FEATURE_COMINTEROP + + // Win32 has the concept of Atoms, where a pointer can either be a pointer + // or an int. If it's less than 64K, this is guaranteed to NOT be a + // pointer since the bottom 64K bytes are reserved in a process' page table. + // We should be careful about deallocating this stuff. Extracted to + // a function to avoid C# problems with lack of support for IntPtr. + // We have 2 of these methods for slightly different semantics for NULL. + private static bool IsWin32Atom(IntPtr ptr) + { +#if FEATURE_PAL + return false; +#else + long lPtr = (long)ptr; + return 0 == (lPtr & HIWORDMASK); +#endif + } + + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private static bool IsNotWin32Atom(IntPtr ptr) + { +#if FEATURE_PAL + return true; +#else + long lPtr = (long)ptr; + return 0 != (lPtr & HIWORDMASK); +#endif + } + + //==================================================================== + // The default character size for the system. This is always 2 because + // the framework only runs on UTF-16 systems. + //==================================================================== + public static readonly int SystemDefaultCharSize = 2; + + //==================================================================== + // The max DBCS character size for the system. + //==================================================================== + public static readonly int SystemMaxDBCSCharSize = GetSystemMaxDBCSCharSize(); + + + //==================================================================== + // The name, title and description of the assembly that will contain + // the dynamically generated interop types. + //==================================================================== + private const String s_strConvertedTypeInfoAssemblyName = "InteropDynamicTypes"; + private const String s_strConvertedTypeInfoAssemblyTitle = "Interop Dynamic Types"; + private const String s_strConvertedTypeInfoAssemblyDesc = "Type dynamically generated from ITypeInfo's"; + private const String s_strConvertedTypeInfoNameSpace = "InteropDynamicTypes"; + + + //==================================================================== + // Helper method to retrieve the system's maximum DBCS character size. + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern int GetSystemMaxDBCSCharSize(); + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringAnsi(IntPtr ptr) + { + if (IntPtr.Zero == ptr) { + return null; + } + else if (IsWin32Atom(ptr)) { + return null; + } + else { + int nb = Win32Native.lstrlenA(ptr); + if( nb == 0) { + return string.Empty; + } + else { + return new String((sbyte *)ptr); + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringAnsi(IntPtr ptr, int len) + { + if (ptr == IntPtr.Zero) + throw new ArgumentNullException("ptr"); + if (len < 0) + throw new ArgumentException("len"); + + return new String((sbyte *)ptr, 0, len); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringUni(IntPtr ptr, int len) + { + if (ptr == IntPtr.Zero) + throw new ArgumentNullException("ptr"); + if (len < 0) + throw new ArgumentException("len"); + + return new String((char *)ptr, 0, len); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static String PtrToStringAuto(IntPtr ptr, int len) + { + // Ansi platforms are no longer supported + return PtrToStringUni(ptr, len); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringUni(IntPtr ptr) + { + if (IntPtr.Zero == ptr) { + return null; + } + else if (IsWin32Atom(ptr)) { + return null; + } + else { + return new String((char *)ptr); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static String PtrToStringAuto(IntPtr ptr) + { + // Ansi platforms are no longer supported + return PtrToStringUni(ptr); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringUTF8(IntPtr ptr) + { + int nbBytes = System.StubHelpers.StubHelpers.strlen((sbyte*)ptr.ToPointer()); + return PtrToStringUTF8(ptr, nbBytes); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static String PtrToStringUTF8(IntPtr ptr,int byteLen) + { + if (byteLen < 0) + { + throw new ArgumentException("byteLen"); + } + else if (IntPtr.Zero == ptr) + { + return null; + } + else if (IsWin32Atom(ptr)) + { + return null; + } + else if (byteLen == 0) + { + return string.Empty; + } + else + { + byte* pByte = (byte*)ptr.ToPointer(); + return Encoding.UTF8.GetString(pByte, byteLen); + } + } + + //==================================================================== + // SizeOf() + //==================================================================== + [System.Runtime.InteropServices.ComVisible(true)] + public static int SizeOf(Object structure) + { + if (structure == null) + throw new ArgumentNullException("structure"); + // we never had a check for generics here + Contract.EndContractBlock(); + + return SizeOfHelper(structure.GetType(), true); + } + + public static int SizeOf<T>(T structure) + { + return SizeOf((object)structure); + } + + [Pure] + public static int SizeOf(Type t) + { + if (t == null) + throw new ArgumentNullException("t"); + if (!(t is RuntimeType)) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t"); + if (t.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + Contract.EndContractBlock(); + + return SizeOfHelper(t, true); + } + + public static int SizeOf<T>() + { + return SizeOf(typeof(T)); + } + + /// <summary> + /// Returns the aligned size of an instance of a value type. + /// </summary> + /// <typeparam name="T">Provide a value type to figure out its size</typeparam> + /// <returns>The aligned size of T in bytes.</returns> + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + internal static uint AlignedSizeOf<T>() where T : struct + { + uint size = SizeOfType(typeof(T)); + if (size == 1 || size == 2) + { + return size; + } + if (IntPtr.Size == 8 && size == 4) + { + return size; + } + return AlignedSizeOfType(typeof(T)); + } + + // Type must be a value type with no object reference fields. We only + // assert this, due to the lack of a suitable generic constraint. + [MethodImpl(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern uint SizeOfType(Type type); + + // Type must be a value type with no object reference fields. We only + // assert this, due to the lack of a suitable generic constraint. + [MethodImpl(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + private static extern uint AlignedSizeOfType(Type type); + +#if !FEATURE_CORECLR // Marshal is critical in CoreCLR, so SafeCritical members trigger Annotator violations + [System.Security.SecuritySafeCritical] +#endif // !FEATURE_CORECLR + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable); + + //==================================================================== + // OffsetOf() + //==================================================================== + public static IntPtr OffsetOf(Type t, String fieldName) + { + if (t == null) + throw new ArgumentNullException("t"); + Contract.EndContractBlock(); + + FieldInfo f = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + if (f == null) + throw new ArgumentException(Environment.GetResourceString("Argument_OffsetOfFieldNotFound", t.FullName), "fieldName"); + RtFieldInfo rtField = f as RtFieldInfo; + if (rtField == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), "fieldName"); + + return OffsetOfHelper(rtField); + } + public static IntPtr OffsetOf<T>(string fieldName) + { + return OffsetOf(typeof(T), fieldName); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern IntPtr OffsetOfHelper(IRuntimeFieldInfo f); + + //==================================================================== + // UnsafeAddrOfPinnedArrayElement() + // + // IMPORTANT NOTICE: This method does not do any verification on the + // array. It must be used with EXTREME CAUTION since passing in + // an array that is not pinned or in the fixed heap can cause + // unexpected results ! + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index); + + [System.Security.SecurityCritical] + public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) + { + return UnsafeAddrOfPinnedArrayElement((Array)arr, index); + } + + //==================================================================== + // Copy blocks from CLR arrays to native memory. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(int[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(char[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(short[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(long[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(float[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(double[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(byte[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int length) + { + CopyToNative(source, startIndex, destination, length); + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void CopyToNative(Object source, int startIndex, IntPtr destination, int length); + + //==================================================================== + // Copy blocks from native memory to CLR arrays + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, int[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, char[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, short[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, long[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, float[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, double[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, byte[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void Copy(IntPtr source, IntPtr[] destination, int startIndex, int length) + { + CopyToManaged(source, destination, startIndex, length); + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void CopyToManaged(IntPtr source, Object destination, int startIndex, int length); + + //==================================================================== + // Read from memory + //==================================================================== + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_RU1")] + [SuppressUnmanagedCodeSecurity] + public static extern byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs); +#else + public static byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe byte ReadByte(IntPtr ptr, int ofs) + { + try + { + byte *addr = (byte *)ptr + ofs; + return *addr; + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static byte ReadByte(IntPtr ptr) + { + return ReadByte(ptr,0); + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_RI2")] + [SuppressUnmanagedCodeSecurity] + public static extern short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); +#else + public static short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe short ReadInt16(IntPtr ptr, int ofs) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x1) == 0) + { + // aligned read + return *((short *)addr); + } + else + { + // unaligned read + short val; + byte *valPtr = (byte *)&val; + valPtr[0] = addr[0]; + valPtr[1] = addr[1]; + return val; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static short ReadInt16(IntPtr ptr) + { + return ReadInt16(ptr, 0); + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_RI4"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [SuppressUnmanagedCodeSecurity] + public static extern int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); +#else + public static int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static unsafe int ReadInt32(IntPtr ptr, int ofs) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x3) == 0) + { + // aligned read + return *((int *)addr); + } + else + { + // unaligned read + int val; + byte *valPtr = (byte *)&val; + valPtr[0] = addr[0]; + valPtr[1] = addr[1]; + valPtr[2] = addr[2]; + valPtr[3] = addr[3]; + return val; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static int ReadInt32(IntPtr ptr) + { + return ReadInt32(ptr,0); + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static IntPtr ReadIntPtr([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) + { + #if BIT64 + return (IntPtr) ReadInt64(ptr, ofs); + #else // 32 + return (IntPtr) ReadInt32(ptr, ofs); + #endif + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static IntPtr ReadIntPtr(IntPtr ptr, int ofs) + { + #if BIT64 + return (IntPtr) ReadInt64(ptr, ofs); + #else // 32 + return (IntPtr) ReadInt32(ptr, ofs); + #endif + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static IntPtr ReadIntPtr(IntPtr ptr) + { + #if BIT64 + return (IntPtr) ReadInt64(ptr, 0); + #else // 32 + return (IntPtr) ReadInt32(ptr, 0); + #endif + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_RI8"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [SuppressUnmanagedCodeSecurity] + public static extern long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs); +#else + public static long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe long ReadInt64(IntPtr ptr, int ofs) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x7) == 0) + { + // aligned read + return *((long *)addr); + } + else + { + // unaligned read + long val; + byte *valPtr = (byte *)&val; + valPtr[0] = addr[0]; + valPtr[1] = addr[1]; + valPtr[2] = addr[2]; + valPtr[3] = addr[3]; + valPtr[4] = addr[4]; + valPtr[5] = addr[5]; + valPtr[6] = addr[6]; + valPtr[7] = addr[7]; + return val; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static long ReadInt64(IntPtr ptr) + { + return ReadInt64(ptr,0); + } + + + //==================================================================== + // Write to memory + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe void WriteByte(IntPtr ptr, int ofs, byte val) + { + try + { + byte *addr = (byte *)ptr + ofs; + *addr = val; + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_WU1")] + [SuppressUnmanagedCodeSecurity] + public static extern void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val); +#else + public static void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteByte(IntPtr ptr, byte val) + { + WriteByte(ptr, 0, val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe void WriteInt16(IntPtr ptr, int ofs, short val) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x1) == 0) + { + // aligned write + *((short *)addr) = val; + } + else + { + // unaligned write + byte *valPtr = (byte *)&val; + addr[0] = valPtr[0]; + addr[1] = valPtr[1]; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_WI2")] + [SuppressUnmanagedCodeSecurity] + public static extern void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val); +#else + public static void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt16(IntPtr ptr, short val) + { + WriteInt16(ptr, 0, val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt16(IntPtr ptr, int ofs, char val) + { + WriteInt16(ptr, ofs, (short)val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt16([In,Out]Object ptr, int ofs, char val) + { + WriteInt16(ptr, ofs, (short)val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt16(IntPtr ptr, char val) + { + WriteInt16(ptr, 0, (short)val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x3) == 0) + { + // aligned write + *((int *)addr) = val; + } + else + { + // unaligned write + byte *valPtr = (byte *)&val; + addr[0] = valPtr[0]; + addr[1] = valPtr[1]; + addr[2] = valPtr[2]; + addr[3] = valPtr[3]; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_WI4")] + [SuppressUnmanagedCodeSecurity] + public static extern void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val); +#else + public static void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt32(IntPtr ptr, int val) + { + WriteInt32(ptr,0,val); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val) + { + #if BIT64 + WriteInt64(ptr, ofs, (long)val); + #else // 32 + WriteInt32(ptr, ofs, (int)val); + #endif + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteIntPtr([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, IntPtr val) + { + #if BIT64 + WriteInt64(ptr, ofs, (long)val); + #else // 32 + WriteInt32(ptr, ofs, (int)val); + #endif + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteIntPtr(IntPtr ptr, IntPtr val) + { + #if BIT64 + WriteInt64(ptr, 0, (long)val); + #else // 32 + WriteInt32(ptr, 0, (int)val); + #endif + } + + [System.Security.SecurityCritical] // auto-generated_required + public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val) + { + try + { + byte *addr = (byte *)ptr + ofs; + if ((unchecked((int)addr) & 0x7) == 0) + { + // aligned write + *((long *)addr) = val; + } + else + { + // unaligned write + byte *valPtr = (byte *)&val; + addr[0] = valPtr[0]; + addr[1] = valPtr[1]; + addr[2] = valPtr[2]; + addr[3] = valPtr[3]; + addr[4] = valPtr[4]; + addr[5] = valPtr[5]; + addr[6] = valPtr[6]; + addr[7] = valPtr[7]; + } + } + catch (NullReferenceException) + { + // this method is documented to throw AccessViolationException on any AV + throw new AccessViolationException(); + } + } + + [System.Security.SecurityCritical] // auto-generated +#if !FEATURE_CORECLR + [DllImport(Win32Native.SHIM, EntryPoint="ND_WI8")] + [SuppressUnmanagedCodeSecurity] + public static extern void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val); +#else + public static void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val) + { + throw new PlatformNotSupportedException(); + } +#endif // !FEATURE_CORECLR + + [System.Security.SecurityCritical] // auto-generated_required + public static void WriteInt64(IntPtr ptr, long val) + { + WriteInt64(ptr, 0, val); + } + + + //==================================================================== + // GetLastWin32Error + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static extern int GetLastWin32Error(); + + + //==================================================================== + // SetLastWin32Error + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern void SetLastWin32Error(int error); + + + //==================================================================== + // GetHRForLastWin32Error + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static int GetHRForLastWin32Error() + { + int dwLastError = GetLastWin32Error(); + if ((dwLastError & 0x80000000) == 0x80000000) + return dwLastError; + else + return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000); + } + + + //==================================================================== + // Prelink + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static void Prelink(MethodInfo m) + { + if (m == null) + throw new ArgumentNullException("m"); + Contract.EndContractBlock(); + + RuntimeMethodInfo rmi = m as RuntimeMethodInfo; + + if (rmi == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo")); + + InternalPrelink(rmi); + } + + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + [SecurityCritical] + private static extern void InternalPrelink(IRuntimeMethodInfo m); + + [System.Security.SecurityCritical] // auto-generated_required + public static void PrelinkAll(Type c) + { + if (c == null) + throw new ArgumentNullException("c"); + Contract.EndContractBlock(); + + MethodInfo[] mi = c.GetMethods(); + if (mi != null) + { + for (int i = 0; i < mi.Length; i++) + { + Prelink(mi[i]); + } + } + } + + //==================================================================== + // NumParamBytes + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static int NumParamBytes(MethodInfo m) + { + if (m == null) + throw new ArgumentNullException("m"); + Contract.EndContractBlock(); + + RuntimeMethodInfo rmi = m as RuntimeMethodInfo; + if (rmi == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo")); + + return InternalNumParamBytes(rmi); + } + + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + [SecurityCritical] + private static extern int InternalNumParamBytes(IRuntimeMethodInfo m); + + //==================================================================== + // Win32 Exception stuff + // These are mostly interesting for Structured exception handling, + // but need to be exposed for all exceptions (not just SEHException). + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [System.Runtime.InteropServices.ComVisible(true)] + public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers(); + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetExceptionCode(); + + + //==================================================================== + // Marshals data from a structure class to a native memory block. + // If the structure contains pointers to allocated blocks and + // "fDeleteOld" is true, this routine will call DestroyStructure() first. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + [System.Runtime.InteropServices.ComVisible(true)] + public static extern void StructureToPtr(Object structure, IntPtr ptr, bool fDeleteOld); + + [System.Security.SecurityCritical] + public static void StructureToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld) + { + StructureToPtr((object)structure, ptr, fDeleteOld); + } + + //==================================================================== + // Marshals data from a native memory block to a preallocated structure class. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [System.Runtime.InteropServices.ComVisible(true)] + public static void PtrToStructure(IntPtr ptr, Object structure) + { + PtrToStructureHelper(ptr, structure, false); + } + + [System.Security.SecurityCritical] + public static void PtrToStructure<T>(IntPtr ptr, T structure) + { + PtrToStructure(ptr, (object)structure); + } + + //==================================================================== + // Creates a new instance of "structuretype" and marshals data from a + // native memory block to it. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [System.Runtime.InteropServices.ComVisible(true)] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable + public static Object PtrToStructure(IntPtr ptr, Type structureType) + { + if (ptr == IntPtr.Zero) return null; + + if (structureType == null) + throw new ArgumentNullException("structureType"); + + if (structureType.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "structureType"); + + RuntimeType rt = structureType.UnderlyingSystemType as RuntimeType; + + if (rt == null) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type"); + + StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; + + Object structure = rt.CreateInstanceDefaultCtor(false /*publicOnly*/, false /*skipCheckThis*/, false /*fillCache*/, ref stackMark); + PtrToStructureHelper(ptr, structure, true); + return structure; + } + + [System.Security.SecurityCritical] + public static T PtrToStructure<T>(IntPtr ptr) + { + return (T)PtrToStructure(ptr, typeof(T)); + } + + //==================================================================== + // Helper function to copy a pointer into a preallocated structure. + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void PtrToStructureHelper(IntPtr ptr, Object structure, bool allowValueClasses); + + + //==================================================================== + // Freeds all substructures pointed to by the native memory block. + // "structureclass" is used to provide layout information. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [System.Runtime.InteropServices.ComVisible(true)] + public static extern void DestroyStructure(IntPtr ptr, Type structuretype); + + [System.Security.SecurityCritical] + public static void DestroyStructure<T>(IntPtr ptr) + { + DestroyStructure(ptr, typeof(T)); + } + + //==================================================================== + // Returns the HInstance for this module. Returns -1 if the module + // doesn't have an HInstance. In Memory (Dynamic) Modules won't have + // an HInstance. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr GetHINSTANCE(Module m) + { + if (m == null) + throw new ArgumentNullException("m"); + Contract.EndContractBlock(); + + RuntimeModule rtModule = m as RuntimeModule; + if (rtModule == null) + { + ModuleBuilder mb = m as ModuleBuilder; + if (mb != null) + rtModule = mb.InternalModule; + } + + if (rtModule == null) + throw new ArgumentNullException("m",Environment.GetResourceString("Argument_MustBeRuntimeModule")); + + return GetHINSTANCE(rtModule.GetNativeHandle()); + } + + [System.Security.SecurityCritical] // auto-generated_required + [SuppressUnmanagedCodeSecurity] + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + private extern static IntPtr GetHINSTANCE(RuntimeModule m); + + //==================================================================== + // Throws a CLR exception based on the HRESULT. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static void ThrowExceptionForHR(int errorCode) + { + if (errorCode < 0) + ThrowExceptionForHRInternal(errorCode, IntPtr.Zero); + } + [System.Security.SecurityCritical] // auto-generated_required + public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo) + { + if (errorCode < 0) + ThrowExceptionForHRInternal(errorCode, errorInfo); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void ThrowExceptionForHRInternal(int errorCode, IntPtr errorInfo); + + + //==================================================================== + // Converts the HRESULT to a CLR exception. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Exception GetExceptionForHR(int errorCode) + { + if (errorCode < 0) + return GetExceptionForHRInternal(errorCode, IntPtr.Zero); + else + return null; + } + [System.Security.SecurityCritical] // auto-generated_required + public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo) + { + if (errorCode < 0) + return GetExceptionForHRInternal(errorCode, errorInfo); + else + return null; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern Exception GetExceptionForHRInternal(int errorCode, IntPtr errorInfo); + + + //==================================================================== + // This method is intended for compiler code generators rather + // than applications. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [ObsoleteAttribute("The GetUnmanagedThunkForManagedMethodPtr method has been deprecated and will be removed in a future release.", false)] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern IntPtr GetUnmanagedThunkForManagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature); + + //==================================================================== + // This method is intended for compiler code generators rather + // than applications. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [ObsoleteAttribute("The GetManagedThunkForUnmanagedMethodPtr method has been deprecated and will be removed in a future release.", false)] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern IntPtr GetManagedThunkForUnmanagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature); + + //==================================================================== + // The hosting APIs allow a sophisticated host to schedule fibers + // onto OS threads, so long as they notify the runtime of this + // activity. A fiber cookie can be redeemed for its managed Thread + // object by calling the following service. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [ObsoleteAttribute("The GetThreadFromFiberCookie method has been deprecated. Use the hosting API to perform this operation.", false)] + public static Thread GetThreadFromFiberCookie(int cookie) + { + if (cookie == 0) + throw new ArgumentException(Environment.GetResourceString("Argument_ArgumentZero"), "cookie"); + Contract.EndContractBlock(); + + return InternalGetThreadFromFiberCookie(cookie); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern Thread InternalGetThreadFromFiberCookie(int cookie); + + + //==================================================================== + // Memory allocation and deallocation. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static IntPtr AllocHGlobal(IntPtr cb) + { + // For backwards compatibility on 32 bit platforms, ensure we pass values between + // Int32.MaxValue and UInt32.MaxValue to Windows. If the binary has had the + // LARGEADDRESSAWARE bit set in the PE header, it may get 3 or 4 GB of user mode + // address space. It is remotely that those allocations could have succeeded, + // though I couldn't reproduce that. In either case, that means we should continue + // throwing an OOM instead of an ArgumentOutOfRangeException for "negative" amounts of memory. + UIntPtr numBytes; +#if BIT64 + numBytes = new UIntPtr(unchecked((ulong)cb.ToInt64())); +#else // 32 + numBytes = new UIntPtr(unchecked((uint)cb.ToInt32())); +#endif + + IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes)); + + if (pNewMem == IntPtr.Zero) { + throw new OutOfMemoryException(); + } + return pNewMem; + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + public static IntPtr AllocHGlobal(int cb) + { + return AllocHGlobal((IntPtr)cb); + } + + [System.Security.SecurityCritical] // auto-generated_required + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static void FreeHGlobal(IntPtr hglobal) + { + if (IsNotWin32Atom(hglobal)) { + if (IntPtr.Zero != Win32Native.LocalFree(hglobal)) { + ThrowExceptionForHR(GetHRForLastWin32Error()); + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb) + { + IntPtr pNewMem = Win32Native.LocalReAlloc(pv, cb, LMEM_MOVEABLE); + if (pNewMem == IntPtr.Zero) { + throw new OutOfMemoryException(); + } + return pNewMem; + } + + + //==================================================================== + // String convertions. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static IntPtr StringToHGlobalAnsi(String s) + { + if (s == null) + { + return IntPtr.Zero; + } + else + { + int nb = (s.Length + 1) * SystemMaxDBCSCharSize; + + // Overflow checking + if (nb < s.Length) + throw new ArgumentOutOfRangeException("s"); + + UIntPtr len = new UIntPtr((uint)nb); + IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len); + + if (hglobal == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + else + { + s.ConvertToAnsi((byte *)hglobal, nb, false, false); + return hglobal; + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static IntPtr StringToHGlobalUni(String s) + { + if (s == null) + { + return IntPtr.Zero; + } + else + { + int nb = (s.Length + 1) * 2; + + // Overflow checking + if (nb < s.Length) + throw new ArgumentOutOfRangeException("s"); + + UIntPtr len = new UIntPtr((uint)nb); + IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len); + + if (hglobal == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + else + { + fixed (char* firstChar = s) + { + String.wstrcpy((char*)hglobal, firstChar, s.Length + 1); + } + return hglobal; + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr StringToHGlobalAuto(String s) + { + // Ansi platforms are no longer supported + return StringToHGlobalUni(s); + } + +#if FEATURE_COMINTEROP + + //==================================================================== + // Converts the CLR exception to an HRESULT. This function also sets + // up an IErrorInfo for the exception. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetHRForException(Exception e); + + //==================================================================== + // Converts the CLR exception to an HRESULT. This function also sets + // up an IErrorInfo for the exception. + // This function is only used in WinRT and converts ObjectDisposedException + // to RO_E_CLOSED + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern int GetHRForException_WinRT(Exception e); + + internal static readonly Guid ManagedNameGuid = new Guid("{0F21F359-AB84-41E8-9A78-36D110E6D2F9}"); + + //==================================================================== + // Given a managed object that wraps a UCOMITypeLib, return its name + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibName(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] + public static String GetTypeLibName(UCOMITypeLib pTLB) + { + return GetTypeLibName((ITypeLib)pTLB); + } + + + //==================================================================== + // Given a managed object that wraps an ITypeLib, return its name + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static String GetTypeLibName(ITypeLib typelib) + { + if (typelib == null) + throw new ArgumentNullException("typelib"); + Contract.EndContractBlock(); + + String strTypeLibName = null; + String strDocString = null; + int dwHelpContext = 0; + String strHelpFile = null; + + typelib.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); + + return strTypeLibName; + } + + //==================================================================== + // Internal version of GetTypeLibName + // Support GUID_ManagedName which aligns with TlbImp + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + internal static String GetTypeLibNameInternal(ITypeLib typelib) + { + if (typelib == null) + throw new ArgumentNullException("typelib"); + Contract.EndContractBlock(); + + // Try GUID_ManagedName first + ITypeLib2 typeLib2 = typelib as ITypeLib2; + if (typeLib2 != null) + { + Guid guid = ManagedNameGuid; + object val; + + try + { + typeLib2.GetCustData(ref guid, out val); + } + catch(Exception) + { + val = null; + } + + if (val != null && val.GetType() == typeof(string)) + { + string customManagedNamespace = (string)val; + customManagedNamespace = customManagedNamespace.Trim(); + if (customManagedNamespace.EndsWith(".DLL", StringComparison.OrdinalIgnoreCase)) + customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4); + else if (customManagedNamespace.EndsWith(".EXE", StringComparison.OrdinalIgnoreCase)) + customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4); + return customManagedNamespace; + } + } + + return GetTypeLibName(typelib); + } + + + //==================================================================== + // Given an managed object that wraps an UCOMITypeLib, return its guid + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibGuid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] + public static Guid GetTypeLibGuid(UCOMITypeLib pTLB) + { + return GetTypeLibGuid((ITypeLib)pTLB); + } + + //==================================================================== + // Given an managed object that wraps an ITypeLib, return its guid + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Guid GetTypeLibGuid(ITypeLib typelib) + { + Guid result = new Guid (); + FCallGetTypeLibGuid (ref result, typelib); + return result; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void FCallGetTypeLibGuid(ref Guid result, ITypeLib pTLB); + + //==================================================================== + // Given a managed object that wraps a UCOMITypeLib, return its lcid + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibLcid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] + public static int GetTypeLibLcid(UCOMITypeLib pTLB) + { + return GetTypeLibLcid((ITypeLib)pTLB); + } + + //==================================================================== + // Given a managed object that wraps an ITypeLib, return its lcid + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetTypeLibLcid(ITypeLib typelib); + + //==================================================================== + // Given a managed object that wraps an ITypeLib, return it's + // version information. + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void GetTypeLibVersion(ITypeLib typeLibrary, out int major, out int minor); + + //==================================================================== + // Given a managed object that wraps an ITypeInfo, return its guid. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated + internal static Guid GetTypeInfoGuid(ITypeInfo typeInfo) + { + Guid result = new Guid (); + FCallGetTypeInfoGuid (ref result, typeInfo); + return result; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void FCallGetTypeInfoGuid(ref Guid result, ITypeInfo typeInfo); + + //==================================================================== + // Given a assembly, return the TLBID that will be generated for the + // typelib exported from the assembly. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Guid GetTypeLibGuidForAssembly(Assembly asm) + { + if (asm == null) + throw new ArgumentNullException("asm"); + Contract.EndContractBlock(); + + RuntimeAssembly rtAssembly = asm as RuntimeAssembly; + if (rtAssembly == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "asm"); + + Guid result = new Guid(); + FCallGetTypeLibGuidForAssembly(ref result, rtAssembly); + return result; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void FCallGetTypeLibGuidForAssembly(ref Guid result, RuntimeAssembly asm); + + //==================================================================== + // Given a assembly, return the version number of the type library + // that would be exported from the assembly. + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void _GetTypeLibVersionForAssembly(RuntimeAssembly inputAssembly, out int majorVersion, out int minorVersion); + + [System.Security.SecurityCritical] // auto-generated_required + public static void GetTypeLibVersionForAssembly(Assembly inputAssembly, out int majorVersion, out int minorVersion) + { + if (inputAssembly == null) + throw new ArgumentNullException("inputAssembly"); + Contract.EndContractBlock(); + + RuntimeAssembly rtAssembly = inputAssembly as RuntimeAssembly; + if (rtAssembly == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "inputAssembly"); + + _GetTypeLibVersionForAssembly(rtAssembly, out majorVersion, out minorVersion); + } + + //==================================================================== + // Given a managed object that wraps an UCOMITypeInfo, return its name + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeInfoName(ITypeInfo pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)] + public static String GetTypeInfoName(UCOMITypeInfo pTI) + { + return GetTypeInfoName((ITypeInfo)pTI); + } + + //==================================================================== + // Given a managed object that wraps an ITypeInfo, return its name + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static String GetTypeInfoName(ITypeInfo typeInfo) + { + if (typeInfo == null) + throw new ArgumentNullException("typeInfo"); + Contract.EndContractBlock(); + + String strTypeLibName = null; + String strDocString = null; + int dwHelpContext = 0; + String strHelpFile = null; + + typeInfo.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile); + + return strTypeLibName; + } + + //==================================================================== + // Internal version of GetTypeInfoName + // Support GUID_ManagedName which aligns with TlbImp + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + internal static String GetTypeInfoNameInternal(ITypeInfo typeInfo, out bool hasManagedName) + { + if (typeInfo == null) + throw new ArgumentNullException("typeInfo"); + Contract.EndContractBlock(); + + // Try ManagedNameGuid first + ITypeInfo2 typeInfo2 = typeInfo as ITypeInfo2; + if (typeInfo2 != null) + { + Guid guid = ManagedNameGuid; + object val; + + try + { + typeInfo2.GetCustData(ref guid, out val); + } + catch(Exception) + { + val = null; + } + + if (val != null && val.GetType() == typeof(string)) + { + hasManagedName = true; + return (string)val; + } + } + + hasManagedName = false; + return GetTypeInfoName(typeInfo); + } + + //==================================================================== + // Get the corresponding managed name as converted by TlbImp + // Used to get the type using GetType() from imported assemblies + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + internal static String GetManagedTypeInfoNameInternal(ITypeLib typeLib, ITypeInfo typeInfo) + { + bool hasManagedName; + string name = GetTypeInfoNameInternal(typeInfo, out hasManagedName); + if (hasManagedName) + return name; + else + return GetTypeLibNameInternal(typeLib) + "." + name; + } + + //==================================================================== + // If a type with the specified GUID is loaded, this method will + // return the reflection type that represents it. Otherwise it returns + // NULL. + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern Type GetLoadedTypeForGUID(ref Guid guid); + +#if !FEATURE_CORECLR // current implementation requires reflection only load + //==================================================================== + // map ITypeInfo* to Type + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Type GetTypeForITypeInfo(IntPtr /* ITypeInfo* */ piTypeInfo) + { + ITypeInfo pTI = null; + ITypeLib pTLB = null; + Type TypeObj = null; + Assembly AsmBldr = null; + TypeLibConverter TlbConverter = null; + int Index = 0; + Guid clsid; + + // If the input ITypeInfo is NULL then return NULL. + if (piTypeInfo == IntPtr.Zero) + return null; + + // Wrap the ITypeInfo in a CLR object. + pTI = (ITypeInfo)GetObjectForIUnknown(piTypeInfo); + + // Check to see if a class exists with the specified GUID. + + clsid = GetTypeInfoGuid(pTI); + TypeObj = GetLoadedTypeForGUID(ref clsid); + + // If we managed to find the type based on the GUID then return it. + if (TypeObj != null) + return TypeObj; + + // There is no type with the specified GUID in the app domain so lets + // try and convert the containing typelib. + try + { + pTI.GetContainingTypeLib(out pTLB, out Index); + } + catch(COMException) + { + pTLB = null; + } + + // Check to see if we managed to get a containing typelib. + if (pTLB != null) + { + // Get the assembly name from the typelib. + AssemblyName AsmName = TypeLibConverter.GetAssemblyNameFromTypelib(pTLB, null, null, null, null, AssemblyNameFlags.None); + String AsmNameString = AsmName.FullName; + + // Check to see if the assembly that will contain the type already exists. + Assembly[] aAssemblies = Thread.GetDomain().GetAssemblies(); + int NumAssemblies = aAssemblies.Length; + for (int i = 0; i < NumAssemblies; i++) + { + if (String.Compare(aAssemblies[i].FullName, + AsmNameString,StringComparison.Ordinal) == 0) + AsmBldr = aAssemblies[i]; + } + + // If we haven't imported the assembly yet then import it. + if (AsmBldr == null) + { + TlbConverter = new TypeLibConverter(); + AsmBldr = TlbConverter.ConvertTypeLibToAssembly(pTLB, + GetTypeLibName(pTLB) + ".dll", 0, new ImporterCallback(), null, null, null, null); + } + + // Load the type object from the imported typelib. + // Call GetManagedTypeInfoNameInternal to align with TlbImp behavior + TypeObj = AsmBldr.GetType(GetManagedTypeInfoNameInternal(pTLB, pTI), true, false); + if (TypeObj != null && !TypeObj.IsVisible) + TypeObj = null; + } + else + { + // If the ITypeInfo does not have a containing typelib then simply + // return Object as the type. + TypeObj = typeof(Object); + } + + return TypeObj; + } +#endif // #if !FEATURE_CORECLR + + // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it + // on Marshal for more consistent API surface. +#if !FEATURE_CORECLR + [System.Security.SecuritySafeCritical] +#endif //!FEATURE_CORECLR + public static Type GetTypeFromCLSID(Guid clsid) + { + return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false); + } + + //==================================================================== + // map Type to ITypeInfo* + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern IntPtr /* ITypeInfo* */ GetITypeInfoForType(Type t); + + //==================================================================== + // return the IUnknown* for an Object if the current context + // is the one where the RCW was first seen. Will return null + // otherwise. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o) + { + return GetIUnknownForObjectNative(o, false); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetIUnknownForObjectInContext(Object o) + { + return GetIUnknownForObjectNative(o, true); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern IntPtr /* IUnknown* */ GetIUnknownForObjectNative(Object o, bool onlyInContext); + + //==================================================================== + // return the raw IUnknown* for a COM Object not related to current + // context + // Does not call AddRef + //==================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr /* IUnknown* */ GetRawIUnknownForComObjectNoAddRef(Object o); + + //==================================================================== + // return the IDispatch* for an Object + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IDispatch */ GetIDispatchForObject(Object o) + { + return GetIDispatchForObjectNative(o, false); + } + + //==================================================================== + // return the IDispatch* for an Object if the current context + // is the one where the RCW was first seen. Will return null + // otherwise. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetIDispatchForObjectInContext(Object o) + { + return GetIDispatchForObjectNative(o, true); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern IntPtr /* IUnknown* */ GetIDispatchForObjectNative(Object o, bool onlyInContext); + + //==================================================================== + // return the IUnknown* representing the interface for the Object + // Object o should support Type T + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T) + { + return GetComInterfaceForObjectNative(o, T, false, true); + } + + [System.Security.SecurityCritical] + public static IntPtr GetComInterfaceForObject<T, TInterface>(T o) + { + return GetComInterfaceForObject(o, typeof(TInterface)); + } + + //==================================================================== + // return the IUnknown* representing the interface for the Object + // Object o should support Type T, it refer the value of mode to + // invoke customized QueryInterface or not + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T, CustomQueryInterfaceMode mode) + { + bool bEnableCustomizedQueryInterface = ((mode == CustomQueryInterfaceMode.Allow) ? true : false); + return GetComInterfaceForObjectNative(o, T, false, bEnableCustomizedQueryInterface); + } + + //==================================================================== + // return the IUnknown* representing the interface for the Object + // Object o should support Type T if the current context + // is the one where the RCW was first seen. Will return null + // otherwise. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr /* IUnknown* */ GetComInterfaceForObjectInContext(Object o, Type t) + { + return GetComInterfaceForObjectNative(o, t, true, true); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern IntPtr /* IUnknown* */ GetComInterfaceForObjectNative(Object o, Type t, bool onlyInContext, bool fEnalbeCustomizedQueryInterface); + + //==================================================================== + // return an Object for IUnknown + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk); + + //==================================================================== + // Return a unique Object given an IUnknown. This ensures that you + // receive a fresh object (we will not look in the cache to match up this + // IUnknown to an already existing object). This is useful in cases + // where you want to be able to call ReleaseComObject on a RCW + // and not worry about other active uses of said RCW. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object GetUniqueObjectForIUnknown(IntPtr unknown); + + //==================================================================== + // return an Object for IUnknown, using the Type T, + // NOTE: + // Type T should be either a COM imported Type or a sub-type of COM + // imported Type + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t); + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, Object o); + + [System.Security.SecurityCritical] + public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o) + { + return CreateAggregatedObject(pOuter, (object)o); + } + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void CleanupUnusedObjectsInCurrentContext(); + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern bool AreComObjectsAvailableForCleanup(); + + //==================================================================== + // check if the object is classic COM component + //==================================================================== +#if !FEATURE_CORECLR // with FEATURE_CORECLR, the whole type is SecurityCritical + [System.Security.SecuritySafeCritical] +#endif + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern bool IsComObject(Object o); + +#endif // FEATURE_COMINTEROP + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr AllocCoTaskMem(int cb) + { + IntPtr pNewMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)cb)); + if (pNewMem == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + return pNewMem; + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static IntPtr StringToCoTaskMemUni(String s) + { + if (s == null) + { + return IntPtr.Zero; + } + else + { + int nb = (s.Length + 1) * 2; + + // Overflow checking + if (nb < s.Length) + throw new ArgumentOutOfRangeException("s"); + + IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb)); + + if (hglobal == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + else + { + fixed (char* firstChar = s) + { + String.wstrcpy((char *)hglobal, firstChar, s.Length + 1); + } + return hglobal; + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static IntPtr StringToCoTaskMemUTF8(String s) + { + const int MAX_UTF8_CHAR_SIZE = 3; + if (s == null) + { + return IntPtr.Zero; + } + else + { + int nb = (s.Length + 1) * MAX_UTF8_CHAR_SIZE; + + // Overflow checking + if (nb < s.Length) + throw new ArgumentOutOfRangeException("s"); + + IntPtr pMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb +1)); + + if (pMem == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + else + { + byte* pbMem = (byte*)pMem; + int nbWritten = s.GetBytesFromEncoding(pbMem, nb, Encoding.UTF8); + pbMem[nbWritten] = 0; + return pMem; + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr StringToCoTaskMemAuto(String s) + { + // Ansi platforms are no longer supported + return StringToCoTaskMemUni(s); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static IntPtr StringToCoTaskMemAnsi(String s) + { + if (s == null) + { + return IntPtr.Zero; + } + else + { + int nb = (s.Length + 1) * SystemMaxDBCSCharSize; + + // Overflow checking + if (nb < s.Length) + throw new ArgumentOutOfRangeException("s"); + + IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb)); + + if (hglobal == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + else + { + s.ConvertToAnsi((byte *)hglobal, nb, false, false); + return hglobal; + } + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void FreeCoTaskMem(IntPtr ptr) + { + if (IsNotWin32Atom(ptr)) { + Win32Native.CoTaskMemFree(ptr); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr ReAllocCoTaskMem(IntPtr pv, int cb) + { + IntPtr pNewMem = Win32Native.CoTaskMemRealloc(pv, new UIntPtr((uint)cb)); + if (pNewMem == IntPtr.Zero && cb != 0) + { + throw new OutOfMemoryException(); + } + return pNewMem; + } + + //==================================================================== + // BSTR allocation and dealocation. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static void FreeBSTR(IntPtr ptr) + { + if (IsNotWin32Atom(ptr)) + { + Win32Native.SysFreeString(ptr); + } + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr StringToBSTR(String s) + { + if (s == null) + return IntPtr.Zero; + + // Overflow checking + if (s.Length + 1 < s.Length) + throw new ArgumentOutOfRangeException("s"); + + IntPtr bstr = Win32Native.SysAllocStringLen(s, s.Length); + if (bstr == IntPtr.Zero) + throw new OutOfMemoryException(); + + return bstr; + } + + [System.Security.SecurityCritical] // auto-generated_required + public static String PtrToStringBSTR(IntPtr ptr) + { + return PtrToStringUni(ptr, (int)Win32Native.SysStringLen(ptr)); + } + +#if FEATURE_COMINTEROP + //==================================================================== + // release the COM component and if the reference hits 0 zombie this object + // further usage of this Object might throw an exception + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static int ReleaseComObject(Object o) + { + __ComObject co = null; + + // Make sure the obj is an __ComObject. + try + { + co = (__ComObject)o; + } + catch (InvalidCastException) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + } + + return co.ReleaseSelf(); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern int InternalReleaseComObject(Object o); + + + //==================================================================== + // release the COM component and zombie this object + // further usage of this Object might throw an exception + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Int32 FinalReleaseComObject(Object o) + { + if (o == null) + throw new ArgumentNullException("o"); + Contract.EndContractBlock(); + + __ComObject co = null; + + // Make sure the obj is an __ComObject. + try + { + co = (__ComObject)o; + } + catch (InvalidCastException) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + } + + co.FinalReleaseSelf(); + + return 0; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InternalFinalReleaseComObject(Object o); + + //==================================================================== + // This method retrieves data from the COM object. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Object GetComObjectData(Object obj, Object key) + { + // Validate that the arguments aren't null. + if (obj == null) + throw new ArgumentNullException("obj"); + if (key == null) + throw new ArgumentNullException("key"); + Contract.EndContractBlock(); + + __ComObject comObj = null; + + // Make sure the obj is an __ComObject. + try + { + comObj = (__ComObject)obj; + } + catch (InvalidCastException) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj"); + } + + if (obj.GetType().IsWindowsRuntimeObject) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj"); + } + + // Retrieve the data from the __ComObject. + return comObj.GetData(key); + } + + //==================================================================== + // This method sets data on the COM object. The data can only be set + // once for a given key and cannot be removed. This function returns + // true if the data has been added, false if the data could not be + // added because there already was data for the specified key. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static bool SetComObjectData(Object obj, Object key, Object data) + { + // Validate that the arguments aren't null. The data can validly be null. + if (obj == null) + throw new ArgumentNullException("obj"); + if (key == null) + throw new ArgumentNullException("key"); + Contract.EndContractBlock(); + + __ComObject comObj = null; + + // Make sure the obj is an __ComObject. + try + { + comObj = (__ComObject)obj; + } + catch (InvalidCastException) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj"); + } + + if (obj.GetType().IsWindowsRuntimeObject) + { + throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj"); + } + + // Retrieve the data from the __ComObject. + return comObj.SetData(key, data); + } + + //==================================================================== + // This method takes the given COM object and wraps it in an object + // of the specified type. The type must be derived from __ComObject. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Object CreateWrapperOfType(Object o, Type t) + { + // Validate the arguments. + if (t == null) + throw new ArgumentNullException("t"); + if (!t.IsCOMObject) + throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotComObject"), "t"); + if (t.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + Contract.EndContractBlock(); + + if (t.IsWindowsRuntimeObject) + throw new ArgumentException(Environment.GetResourceString("Argument_TypeIsWinRTType"), "t"); + + // Check for the null case. + if (o == null) + return null; + + // Make sure the object is a COM object. + if (!o.GetType().IsCOMObject) + throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o"); + if (o.GetType().IsWindowsRuntimeObject) + throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "o"); + + // Check to see if the type of the object is the requested type. + if (o.GetType() == t) + return o; + + // Check to see if we already have a cached wrapper for this type. + Object Wrapper = GetComObjectData(o, t); + if (Wrapper == null) + { + // Create the wrapper for the specified type. + Wrapper = InternalCreateWrapperOfType(o, t); + + // Attempt to cache the wrapper on the object. + if (!SetComObjectData(o, t, Wrapper)) + { + // Another thead already cached the wrapper so use that one instead. + Wrapper = GetComObjectData(o, t); + } + } + + return Wrapper; + } + + [System.Security.SecurityCritical] + public static TWrapper CreateWrapperOfType<T, TWrapper>(T o) + { + return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper)); + } + + //==================================================================== + // Helper method called from CreateWrapperOfType. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern Object InternalCreateWrapperOfType(Object o, Type t); + + //==================================================================== + // There may be a thread-based cache of COM components. This service can + // force the aggressive release of the current thread's cache. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [Obsolete("This API did not perform any operation and will be removed in future versions of the CLR.", false)] + public static void ReleaseThreadCache() + { + } + + //==================================================================== + // check if the type is visible from COM. + //==================================================================== + [System.Security.SecuritySafeCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern bool IsTypeVisibleFromCom(Type t); + + //==================================================================== + // IUnknown Helpers + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int /* HRESULT */ QueryInterface(IntPtr /* IUnknown */ pUnk, ref Guid iid, out IntPtr ppv); + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int /* ULONG */ AddRef(IntPtr /* IUnknown */ pUnk ); + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk ); + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void GetNativeVariantForObject(Object obj, /* VARIANT * */ IntPtr pDstNativeVariant); + + [System.Security.SecurityCritical] + public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant) + { + GetNativeVariantForObject((object)obj, pDstNativeVariant); + } + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant ); + + [System.Security.SecurityCritical] + public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant) + { + return (T)GetObjectForNativeVariant(pSrcNativeVariant); + } + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern Object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars ); + + [System.Security.SecurityCritical] + public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars) + { + object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars); + T[] result = null; + + if (objects != null) + { + result = new T[objects.Length]; + Array.Copy(objects, result, objects.Length); + } + + return result; + } + + /// <summary> + /// <para>Returns the first valid COM slot that GetMethodInfoForSlot will work on + /// This will be 3 for IUnknown based interfaces and 7 for IDispatch based interfaces. </para> + /// </summary> + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetStartComSlot(Type t); + + /// <summary> + /// <para>Returns the last valid COM slot that GetMethodInfoForSlot will work on. </para> + /// </summary> + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern int GetEndComSlot(Type t); + + /// <summary> + /// <para>Returns the MemberInfo that COM callers calling through the exposed + /// vtable on the given slot will be calling. The slot should take into account + /// if the exposed interface is IUnknown based or IDispatch based. + /// For classes, the lookup is done on the default interface that will be + /// exposed for the class. </para> + /// </summary> + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern MemberInfo GetMethodInfoForComSlot(Type t, int slot, ref ComMemberType memberType); + + /// <summary> + /// <para>Returns the COM slot for a memeber info, taking into account whether + /// the exposed interface is IUnknown based or IDispatch based</para> + /// </summary> + [System.Security.SecurityCritical] // auto-generated_required + public static int GetComSlotForMethodInfo(MemberInfo m) + { + if (m== null) + throw new ArgumentNullException("m"); + + if (!(m is RuntimeMethodInfo)) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "m"); + + if (!m.DeclaringType.IsInterface) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeInterfaceMethod"), "m"); + if (m.DeclaringType.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "m"); + Contract.EndContractBlock(); + + return InternalGetComSlotForMethodInfo((IRuntimeMethodInfo)m); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern int InternalGetComSlotForMethodInfo(IRuntimeMethodInfo m); + + //==================================================================== + // This method generates a GUID for the specified type. If the type + // has a GUID in the metadata then it is returned otherwise a stable + // guid GUID is generated based on the fully qualified name of the + // type. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Guid GenerateGuidForType(Type type) + { + Guid result = new Guid (); + FCallGenerateGuidForType (ref result, type); + return result; + } + + // The full assembly name is used to compute the GUID, so this should be SxS-safe + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern void FCallGenerateGuidForType(ref Guid result, Type type); + + //==================================================================== + // This method generates a PROGID for the specified type. If the type + // has a PROGID in the metadata then it is returned otherwise a stable + // PROGID is generated based on the fully qualified name of the + // type. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static String GenerateProgIdForType(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + if (type.IsImport) + throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustNotBeComImport"), "type"); + if (type.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type"); + Contract.EndContractBlock(); + + if (!RegistrationServices.TypeRequiresRegistrationHelper(type)) + throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"), "type"); + + IList<CustomAttributeData> cas = CustomAttributeData.GetCustomAttributes(type); + for (int i = 0; i < cas.Count; i ++) + { + if (cas[i].Constructor.DeclaringType == typeof(ProgIdAttribute)) + { + // Retrieve the PROGID string from the ProgIdAttribute. + IList<CustomAttributeTypedArgument> caConstructorArgs = cas[i].ConstructorArguments; + Contract.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1"); + + CustomAttributeTypedArgument progIdConstructorArg = caConstructorArgs[0]; + Contract.Assert(progIdConstructorArg.ArgumentType == typeof(String), "progIdConstructorArg.ArgumentType == typeof(String)"); + + String strProgId = (String)progIdConstructorArg.Value; + + if (strProgId == null) + strProgId = String.Empty; + + return strProgId; + } + } + + // If there is no prog ID attribute then use the full name of the type as the prog id. + return type.FullName; + } + + //==================================================================== + // This method binds to the specified moniker. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Object BindToMoniker(String monikerName) + { + Object obj = null; + IBindCtx bindctx = null; + CreateBindCtx(0, out bindctx); + + UInt32 cbEaten; + IMoniker pmoniker = null; + MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker); + + BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj); + return obj; + } + + //==================================================================== + // This method gets the currently running object. + //==================================================================== + [System.Security.SecurityCritical] // auto-generated_required + public static Object GetActiveObject(String progID) + { + Object obj = null; + Guid clsid; + + // Call CLSIDFromProgIDEx first then fall back on CLSIDFromProgID if + // CLSIDFromProgIDEx doesn't exist. + try + { + CLSIDFromProgIDEx(progID, out clsid); + } +// catch + catch(Exception) + { + CLSIDFromProgID(progID, out clsid); + } + + GetActiveObject(ref clsid, IntPtr.Zero, out obj); + return obj; + } + + [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid); + + [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid); + + [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void CreateBindCtx(UInt32 reserved, out IBindCtx ppbc); + + [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] String szUserName, out UInt32 pchEaten, out IMoniker ppmk); + + [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void BindMoniker(IMoniker pmk, UInt32 grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult); + + [DllImport(Microsoft.Win32.Win32Native.OLEAUT32, PreserveSig = false)] + [SuppressUnmanagedCodeSecurity] + [System.Security.SecurityCritical] // auto-generated + private static extern void GetActiveObject(ref Guid rclsid, IntPtr reserved, [MarshalAs(UnmanagedType.Interface)] out Object ppunk); + + //======================================================================== + // Private method called from remoting to support ServicedComponents. + //======================================================================== + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern bool InternalSwitchCCW(Object oldtp, Object newtp); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern Object InternalWrapIUnknownWithComObject(IntPtr i); + + //======================================================================== + // Private method called from EE upon use of license/ICF2 marshaling. + //======================================================================== + [SecurityCritical] + private static IntPtr LoadLicenseManager() + { + Assembly sys = Assembly.Load("System, Version="+ ThisAssembly.Version + + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken); + Type t = sys.GetType("System.ComponentModel.LicenseManager"); + if (t == null || !t.IsVisible) + return IntPtr.Zero; + return t.TypeHandle.Value; + } + + [System.Security.SecurityCritical] // auto-generated_required + [MethodImplAttribute(MethodImplOptions.InternalCall)] + public static extern void ChangeWrapperHandleStrength(Object otp, bool fIsWeak); + + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk); + +#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType); +#endif + + //======================================================================== + // Create activation factory and wraps it with a unique RCW + //======================================================================== + [System.Security.SecurityCritical] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern object GetNativeActivationFactory(Type type); + + //======================================================================== + // Methods allowing retrieval of the IIDs exposed by an underlying WinRT + // object, as specified by the object's IInspectable::GetIids() + //======================================================================== + [System.Security.SecurityCritical] + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + private static extern void _GetInspectableIids(ObjectHandleOnStack obj, ObjectHandleOnStack guids); + + [System.Security.SecurityCritical] + internal static System.Guid[] GetInspectableIids(object obj) + { + System.Guid[] result = null; + System.__ComObject comObj = obj as System.__ComObject; + if (comObj != null) + { + _GetInspectableIids(JitHelpers.GetObjectHandleOnStack(ref comObj), + JitHelpers.GetObjectHandleOnStack(ref result)); + } + + return result; + } + + //======================================================================== + // Methods allowing retrieval of the cached WinRT type corresponding to + // the specified GUID + //======================================================================== + [System.Security.SecurityCritical] + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + private static extern void _GetCachedWinRTTypeByIid( + ObjectHandleOnStack appDomainObj, + System.Guid iid, + out IntPtr rthHandle); + + [System.Security.SecurityCritical] + internal static System.Type GetCachedWinRTTypeByIid( + System.AppDomain ad, + System.Guid iid) + { + IntPtr rthHandle; + _GetCachedWinRTTypeByIid(JitHelpers.GetObjectHandleOnStack(ref ad), + iid, + out rthHandle); + System.Type res = Type.GetTypeFromHandleUnsafe(rthHandle); + return res; + } + + + //======================================================================== + // Methods allowing retrieval of the WinRT types cached in the specified + // app domain + //======================================================================== + [System.Security.SecurityCritical] + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] + private static extern void _GetCachedWinRTTypes( + ObjectHandleOnStack appDomainObj, + ref int epoch, + ObjectHandleOnStack winrtTypes); + + [System.Security.SecurityCritical] + internal static System.Type[] GetCachedWinRTTypes( + System.AppDomain ad, + ref int epoch) + { + System.IntPtr[] res = null; + + _GetCachedWinRTTypes(JitHelpers.GetObjectHandleOnStack(ref ad), + ref epoch, + JitHelpers.GetObjectHandleOnStack(ref res)); + + System.Type[] result = new System.Type[res.Length]; + for (int i = 0; i < res.Length; ++i) + { + result[i] = Type.GetTypeFromHandleUnsafe(res[i]); + } + + return result; + } + + [System.Security.SecurityCritical] + internal static System.Type[] GetCachedWinRTTypes( + System.AppDomain ad) + { + int dummyEpoch = 0; + return GetCachedWinRTTypes(ad, ref dummyEpoch); + } + + +#endif // FEATURE_COMINTEROP + + [System.Security.SecurityCritical] // auto-generated_required + public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) + { + // Validate the parameters + if (ptr == IntPtr.Zero) + throw new ArgumentNullException("ptr"); + + if (t == null) + throw new ArgumentNullException("t"); + Contract.EndContractBlock(); + + if ((t as RuntimeType) == null) + throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t"); + + if (t.IsGenericType) + throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t"); + + Type c = t.BaseType; + if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate))) + throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "t"); + + return GetDelegateForFunctionPointerInternal(ptr, t); + } + + [System.Security.SecurityCritical] + public static TDelegate GetDelegateForFunctionPointer<TDelegate>(IntPtr ptr) + { + return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate)); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t); + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr GetFunctionPointerForDelegate(Delegate d) + { + if (d == null) + throw new ArgumentNullException("d"); + Contract.EndContractBlock(); + + return GetFunctionPointerForDelegateInternal(d); + } + + [System.Security.SecurityCritical] + public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d) + { + return GetFunctionPointerForDelegate((Delegate)(object)d); + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d); + +#if FEATURE_LEGACYSURFACE + +#if FEATURE_COMINTEROP + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr SecureStringToBSTR(SecureString s) { + if( s == null) { + throw new ArgumentNullException("s"); + } + Contract.EndContractBlock(); + + return s.ToBSTR(); + } +#endif + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s) { + if( s == null) { + throw new ArgumentNullException("s"); + } + Contract.EndContractBlock(); + + return s.ToAnsiStr(false); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s) + { + if (s == null) + { + throw new ArgumentNullException("s"); + } + Contract.EndContractBlock(); + + return s.ToUniStr(false); + } + +#endif // FEATURE_LEGACYSURFACE + + +#if FEATURE_COMINTEROP + [System.Security.SecurityCritical] // auto-generated_required + public static void ZeroFreeBSTR(IntPtr s) + { + Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.SysStringLen(s) * 2)); + FreeBSTR(s); + } +#endif + + [System.Security.SecurityCritical] // auto-generated_required + public static void ZeroFreeCoTaskMemAnsi(IntPtr s) + { + Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s))); + FreeCoTaskMem(s); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void ZeroFreeCoTaskMemUnicode(IntPtr s) + { + Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2)); + FreeCoTaskMem(s); + } + + [System.Security.SecurityCritical] // auto-generated_required + unsafe public static void ZeroFreeCoTaskMemUTF8(IntPtr s) + { + Win32Native.ZeroMemory(s, (UIntPtr)System.StubHelpers.StubHelpers.strlen((sbyte*)s)); + FreeCoTaskMem(s); + } + +#if FEATURE_LEGACYSURFACE + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s) { + if( s == null) { + throw new ArgumentNullException("s"); + } + Contract.EndContractBlock(); + + return s.ToAnsiStr(true); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s) { + if( s == null) { + throw new ArgumentNullException("s"); + } + Contract.EndContractBlock(); + + return s.ToUniStr(true); + } +#endif // FEATURE_LEGACYSURFACE + + [System.Security.SecurityCritical] // auto-generated_required + public static void ZeroFreeGlobalAllocAnsi(IntPtr s) { + Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s))); + FreeHGlobal(s); + } + + [System.Security.SecurityCritical] // auto-generated_required + public static void ZeroFreeGlobalAllocUnicode(IntPtr s) { + Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2)); + FreeHGlobal(s); + } + } + +#if FEATURE_COMINTEROP && !FEATURE_CORECLR // current implementation requires reflection only load + //======================================================================== + // Typelib importer callback implementation. + //======================================================================== + internal class ImporterCallback : ITypeLibImporterNotifySink + { + public void ReportEvent(ImporterEventKind EventKind, int EventCode, String EventMsg) + { + } + + [System.Security.SecuritySafeCritical] // overrides transparent public member + public Assembly ResolveRef(Object TypeLib) + { + try + { + // Create the TypeLibConverter. + ITypeLibConverter TLBConv = new TypeLibConverter(); + + // Convert the typelib. + return TLBConv.ConvertTypeLibToAssembly(TypeLib, + Marshal.GetTypeLibName((ITypeLib)TypeLib) + ".dll", + 0, + new ImporterCallback(), + null, + null, + null, + null); + } + catch(Exception) +// catch + { + return null; + } + } + } +#endif // FEATURE_COMINTEROP && !FEATURE_CORECLR +} + diff --git a/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs b/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs new file mode 100644 index 0000000000..b916778019 --- /dev/null +++ b/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================================= +** +** +** Purpose: This exception is thrown when the marshaller encounters a signature +** that has an invalid MarshalAs CA for a given argument or is not +** supported. +** +=============================================================================*/ + +namespace System.Runtime.InteropServices { + + using System; + using System.Runtime.Serialization; + + [System.Runtime.InteropServices.ComVisible(true)] + [Serializable] + public class MarshalDirectiveException : SystemException { + public MarshalDirectiveException() + : base(Environment.GetResourceString("Arg_MarshalDirectiveException")) { + SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE); + } + + public MarshalDirectiveException(String message) + : base(message) { + SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE); + } + + public MarshalDirectiveException(String message, Exception inner) + : base(message, inner) { + SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE); + } + + protected MarshalDirectiveException(SerializationInfo info, StreamingContext context) : base(info, context) { + } + } +} |