1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: __ComObject
**
**
** __ComObject is the root class for all COM wrappers. This class
** defines only the basics. This class is used for wrapping COM objects
** accessed from COM+
**
**
===========================================================*/
namespace System {
using System;
using System.Collections;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Security.Permissions;
internal class __ComObject : MarshalByRefObject
{
private Hashtable m_ObjectToDataMap;
/*============================================================
** default constructor
** can't instantiate this directly
=============================================================*/
protected __ComObject ()
{
}
//====================================================================
// Overrides ToString() to make sure we call to IStringable if the
// COM object implements it in the case of weakly typed RCWs
//====================================================================
public override string ToString()
{
//
// Only do the IStringable cast when running under AppX for better compat
// Otherwise we could do a IStringable cast in classic apps which could introduce
// a thread transition which would lead to deadlock
//
if (AppDomain.IsAppXModel())
{
// Check whether the type implements IStringable.
IStringable stringableType = this as IStringable;
if (stringableType != null)
{
return stringableType.ToString();
}
}
return base.ToString();
}
[System.Security.SecurityCritical] // auto-generated
internal IntPtr GetIUnknown(out bool fIsURTAggregated)
{
fIsURTAggregated = !GetType().IsDefined(typeof(ComImportAttribute), false);
return System.Runtime.InteropServices.Marshal.GetIUnknownForObject(this);
}
//====================================================================
// This method retrieves the data associated with the specified
// key if any such data exists for the current __ComObject.
//====================================================================
internal Object GetData(Object key)
{
Object data = null;
// Synchronize access to the map.
lock(this)
{
// If the map hasn't been allocated, then there can be no data for the specified key.
if (m_ObjectToDataMap != null)
{
// Look up the data in the map.
data = m_ObjectToDataMap[key];
}
}
return data;
}
//====================================================================
// This method sets the data for the specified key on the current
// __ComObject.
//====================================================================
internal bool SetData(Object key, Object data)
{
bool bAdded = false;
// Synchronize access to the map.
lock(this)
{
// If the map hasn't been allocated yet, allocate it.
if (m_ObjectToDataMap == null)
m_ObjectToDataMap = new Hashtable();
// If there isn't already data in the map then add it.
if (m_ObjectToDataMap[key] == null)
{
m_ObjectToDataMap[key] = data;
bAdded = true;
}
}
return bAdded;
}
//====================================================================
// This method is called from within the EE and releases all the
// cached data for the __ComObject.
//====================================================================
[System.Security.SecurityCritical] // auto-generated
internal void ReleaseAllData()
{
// Synchronize access to the map.
lock(this)
{
// If the map hasn't been allocated, then there is nothing to do.
if (m_ObjectToDataMap != null)
{
foreach (Object o in m_ObjectToDataMap.Values)
{
// Note: the value could be an object[]
// We are fine for now as object[] doesn't implement IDisposable nor derive from __ComObject
// If the object implements IDisposable, then call Dispose on it.
IDisposable DisposableObj = o as IDisposable;
if (DisposableObj != null)
DisposableObj.Dispose();
// If the object is a derived from __ComObject, then call Marshal.ReleaseComObject on it.
__ComObject ComObj = o as __ComObject;
if (ComObj != null)
Marshal.ReleaseComObject(ComObj);
}
// Set the map to null to indicate it has been cleaned up.
m_ObjectToDataMap = null;
}
}
}
//====================================================================
// This method is called from within the EE and is used to handle
// calls on methods of event interfaces.
//====================================================================
[System.Security.SecurityCritical] // auto-generated
internal Object GetEventProvider(RuntimeType t)
{
// Check to see if we already have a cached event provider for this type.
Object EvProvider = GetData(t);
// If we don't then we need to create one.
if (EvProvider == null)
EvProvider = CreateEventProvider(t);
return EvProvider;
}
[System.Security.SecurityCritical] // auto-generated
internal int ReleaseSelf()
{
return Marshal.InternalReleaseComObject(this);
}
[System.Security.SecurityCritical] // auto-generated
internal void FinalReleaseSelf()
{
Marshal.InternalFinalReleaseComObject(this);
}
[System.Security.SecurityCritical] // auto-generated
#if !FEATURE_CORECLR
[ReflectionPermissionAttribute(SecurityAction.Assert, MemberAccess=true)]
#endif
private Object CreateEventProvider(RuntimeType t)
{
// Create the event provider for the specified type.
Object EvProvider = Activator.CreateInstance(t, Activator.ConstructorDefault | BindingFlags.NonPublic, null, new Object[]{this}, null);
// Attempt to cache the wrapper on the object.
if (!SetData(t, EvProvider))
{
// Dispose the event provider if it implements IDisposable.
IDisposable DisposableEvProv = EvProvider as IDisposable;
if (DisposableEvProv != null)
DisposableEvProv.Dispose();
// Another thead already cached the wrapper so use that one instead.
EvProvider = GetData(t);
}
return EvProvider;
}
}
}
|