a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
99 lines
3.3 KiB
C#
99 lines
3.3 KiB
C#
/* ****************************************************************************
|
|
*
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* This source code is subject to terms and conditions of the Microsoft Public License. A
|
|
* copy of the license can be found in the License.html file at the root of this distribution. If
|
|
* you cannot locate the Microsoft Public License, please send an email to
|
|
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
|
|
* by the terms of the Microsoft Public License.
|
|
*
|
|
* You must not remove this notice, or any other, from this software.
|
|
*
|
|
*
|
|
* ***************************************************************************/
|
|
using System; using Microsoft;
|
|
|
|
|
|
#if !SILVERLIGHT // ComObject
|
|
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
|
|
#if CODEPLEX_40
|
|
namespace System.Dynamic {
|
|
#else
|
|
namespace Microsoft.Scripting {
|
|
#endif
|
|
/// <summary>
|
|
/// ComEventSinksContainer is just a regular list with a finalizer.
|
|
/// This list is usually attached as a custom data for RCW object and
|
|
/// is finalized whenever RCW is finalized.
|
|
/// </summary>
|
|
internal class ComEventSinksContainer : List<ComEventSink>, IDisposable {
|
|
private ComEventSinksContainer() {
|
|
}
|
|
|
|
private static readonly object _ComObjectEventSinksKey = new object();
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
|
|
[SecurityCritical]
|
|
public static ComEventSinksContainer FromRuntimeCallableWrapper(object rcw, bool createIfNotFound) {
|
|
// !!! Marshal.Get/SetComObjectData has a LinkDemand for UnmanagedCode which will turn into
|
|
// a full demand. We need to avoid this by making this method SecurityCritical
|
|
object data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
|
|
if (data != null || createIfNotFound == false) {
|
|
return (ComEventSinksContainer)data;
|
|
}
|
|
|
|
lock (_ComObjectEventSinksKey) {
|
|
data = Marshal.GetComObjectData(rcw, _ComObjectEventSinksKey);
|
|
if (data != null) {
|
|
return (ComEventSinksContainer)data;
|
|
}
|
|
|
|
ComEventSinksContainer comEventSinks = new ComEventSinksContainer();
|
|
if (!Marshal.SetComObjectData(rcw, _ComObjectEventSinksKey, comEventSinks)) {
|
|
throw Error.SetComObjectDataFailed();
|
|
}
|
|
|
|
return comEventSinks;
|
|
}
|
|
}
|
|
|
|
#region IDisposable Members
|
|
|
|
#if CLR2
|
|
[SecurityCritical, SecurityTreatAsSafe]
|
|
#else
|
|
[SecuritySafeCritical]
|
|
#endif
|
|
public void Dispose() {
|
|
DisposeAll();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
#endregion
|
|
|
|
[SecurityCritical]
|
|
private void DisposeAll() {
|
|
foreach (ComEventSink sink in this) {
|
|
sink.Dispose();
|
|
}
|
|
}
|
|
|
|
#if CLR2
|
|
[SecurityCritical, SecurityTreatAsSafe]
|
|
#else
|
|
[SecuritySafeCritical]
|
|
#endif
|
|
~ComEventSinksContainer() {
|
|
DisposeAll();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|