// Private. Objects must be created with CreateProxy. ComInteropProxy (Type t) : base (t) { // object only created here // .ctor is called later com_object = __ComObject.CreateRCW (t); }
[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; } } }
public override bool Equals(object obj) { this.CheckIUnknown(); if (obj == null) { return(false); } __ComObject _ComObject = obj as __ComObject; return(_ComObject != null && this.iunknown == _ComObject.IUnknown); }
public override bool Equals(object obj) { CheckIUnknown(); if (obj == null) { return(false); } __ComObject co = obj as __ComObject; if ((object)co == null) { return(false); } return(iunknown == co.IUnknown); }
internal void ReleaseAllData() { lock (this) { if (this.m_ObjectToDataMap != null) { foreach (object obj2 in this.m_ObjectToDataMap.Values) { IDisposable disposable = obj2 as IDisposable; if (disposable != null) { disposable.Dispose(); } __ComObject o = obj2 as __ComObject; if (o != null) { Marshal.ReleaseComObject(o); } } this.m_ObjectToDataMap = null; } } }
internal void ReleaseAllData() { lock (this) { if (this.m_ObjectToDataMap == null) { return; } foreach (object item_0 in (IEnumerable)this.m_ObjectToDataMap.Values) { IDisposable local_3 = item_0 as IDisposable; if (local_3 != null) { local_3.Dispose(); } __ComObject local_4 = item_0 as __ComObject; if (local_4 != null) { Marshal.ReleaseComObject((object)local_4); } } this.m_ObjectToDataMap = (Hashtable)null; } }
/// <summary> /// Returns the existing RCW or create a new RCW from the COM interface pointer /// NOTE: This does not do any unboxing at all. /// </summary> /// <param name="expectedContext"> /// The current context of this thread. If it is passed and is not Default, we'll check whether the /// returned RCW from cache matches this expected context. If it is not a match (from a different /// context, and is not free threaded), we'll go ahead ignoring the cached entry, and create a new /// RCW instead - which will always end up in the current context /// We'll skip the check if current == ContextCookie.Default. /// </param> private static object ComInterfaceToComObjectInternal_NoCache( IntPtr pComItf, IntPtr pComIdentityIUnknown, RuntimeTypeHandle interfaceType, RuntimeTypeHandle classTypeInSignature, ContextCookie expectedContext, CreateComObjectFlags flags, out string className ) { className = null; // // Lookup RCW in global RCW cache based on the identity IUnknown // __ComObject comObject = ComObjectCache.Lookup(pComIdentityIUnknown); if (comObject != null) { bool useThisComObject = true; if (!expectedContext.IsDefault) { // // Make sure the returned RCW matches the context we specify (if any) // if (!comObject.IsFreeThreaded && !comObject.ContextCookie.Equals(expectedContext)) { // // This is a mismatch. // We only care about context for WinRT factory RCWs (which is the only place we are // passing in the context right now). // When we get back a WinRT factory RCW created in a different context. This means the // factory is a singleton, and the returned IActivationFactory could be either one of // the following: // 1) A raw pointer, and it acts like a free threaded object // 2) A proxy that is used across different contexts. It might maintain a list of contexts // that it is marshaled to, and will fail to be called if it is not marshaled to this // context yet. // // In this case, it is unsafe to use this RCW in this context and we should proceed // to create a duplicated one instead. It might make sense to have a context-sensitive // RCW cache but I don't think this case will be common enough to justify it // // @TODO: Check for DCOM proxy as well useThisComObject = false; } } if (useThisComObject) { // // We found one - AddRef and return // comObject.AddRef(); return comObject; } } string winrtClassName = null; bool isSealed = false; if (!classTypeInSignature.IsNull()) { isSealed = classTypeInSignature.IsSealed(); } // // Only look at runtime class name if the class type in signature is not sealed // NOTE: In the case of System.Uri, we are not pass the class type, only the interface // if (!isSealed && (flags & CreateComObjectFlags.SkipTypeResolutionAndUnboxing) == 0) { IntPtr pInspectable; bool needRelease = false; if (interfaceType.IsSupportIInspectable()) { // // Use the interface pointer as IInspectable as we know it is indeed a WinRT interface that // derives from IInspectable // pInspectable = pComItf; } else if ((flags & CreateComObjectFlags.IsWinRTObject) != 0) { // // Otherwise, if someone tells us that this is a WinRT object, but we don't have a // IInspectable interface at hand, we'll QI for it // pInspectable = McgMarshal.ComQueryInterfaceNoThrow(pComItf, ref Interop.COM.IID_IInspectable); needRelease = true; } else { pInspectable = default(IntPtr); } try { if (pInspectable != default(IntPtr)) { className = McgComHelpers.GetRuntimeClassName(pInspectable); winrtClassName = className; } } finally { if (needRelease && pInspectable != default(IntPtr)) { McgMarshal.ComRelease(pInspectable); pInspectable = default(IntPtr); } } } // // 1. Prefer using the class returned from GetRuntimeClassName // 2. Otherwise use the class (if there) in the signature // 3. Out of options - create __ComObject // RuntimeTypeHandle classTypeToCreateRCW = default(RuntimeTypeHandle); RuntimeTypeHandle interfaceTypeFromName = default(RuntimeTypeHandle); if (!String.IsNullOrEmpty(className)) { if (!McgModuleManager.TryGetClassTypeFromName(className, out classTypeToCreateRCW)) { // // If we can't find the class name in our map, try interface as well // Such as IVector<Int32> // This apparently won't work if we haven't seen the interface type in MCG // McgModuleManager.TryGetInterfaceTypeFromName(className, out interfaceTypeFromName); } } if (classTypeToCreateRCW.IsNull()) classTypeToCreateRCW = classTypeInSignature; // Use identity IUnknown to create the new RCW // @TODO: Transfer the ownership of ref count to the RCW if (classTypeToCreateRCW.IsNull()) { // // Create a weakly typed RCW because we have no information about this particular RCW // @TODO - what if this RCW is not seen by MCG but actually exists in WinMD and therefore we // are missing GCPressure and ComMarshallingType information for this object? // comObject = new __ComObject(pComIdentityIUnknown, default(RuntimeTypeHandle)); } else { // // Create a strongly typed RCW based on RuntimeTypeHandle // comObject = CreateComObjectInternal(classTypeToCreateRCW, pComIdentityIUnknown); // Use identity IUnknown to create the new RCW } #if DEBUG // // Remember the runtime class name for debugging purpose // This way you can tell what the class name is, even when we failed to create a strongly typed // RCW for it // comObject.m_runtimeClassName = className; #endif // // Make sure we QI for that interface // if (!interfaceType.IsNull()) { comObject.QueryInterface_NoAddRef_Internal(interfaceType, /* cacheOnly= */ false, /* throwOnQueryInterfaceFailure= */ false); } return comObject; }
internal static __ComGenericInterfaceDispatcher CreateGenericComDispatcher(RuntimeTypeHandle genericDispatcherDef, RuntimeTypeHandle[] genericArguments, __ComObject comThisPointer) { #if !RHTESTCL && !CORECLR && !CORERT Debug.Assert(genericDispatcherDef.IsGenericTypeDefinition()); Debug.Assert(genericArguments != null && genericArguments.Length > 0); RuntimeTypeHandle instantiatedDispatcherType; if (!Internal.Runtime.TypeLoader.TypeLoaderEnvironment.Instance.TryGetConstructedGenericTypeForComponents(genericDispatcherDef, genericArguments, out instantiatedDispatcherType)) return null; // ERROR __ComGenericInterfaceDispatcher dispatcher = (__ComGenericInterfaceDispatcher)InteropExtensions.RuntimeNewObject(instantiatedDispatcherType); dispatcher.m_comObject = comThisPointer; return dispatcher; #else return null; #endif }
internal ComInteropProxy (IntPtr pUnk, Type t) : base (t) { com_object = new __ComObject (pUnk); CacheProxy (); }
internal static bool WalkOneRCW(__ComObject comObject) { __com_IJupiterObject* pJupiterObject = comObject.GetIJupiterObject_NoAddRef(); s_currentComObjectToWalk = comObject; // // Start building references from this RCW to all dependent CCWs // // NOTE: StdCallCOOP is used instead of Calli to avoid deadlock // int hr = CalliIntrinsics.StdCallCOOP( pJupiterObject->pVtable->pfnFindDependentWrappers, pJupiterObject, GetDependentWrapperCallbackObject() ); s_currentComObjectToWalk = null; return (hr >= 0); }
/// <summary> /// Reporting to Jupiter that we've done one Release to this object instance /// /// The ref count reporting is needed for Jupiter to determine whether there is something other than /// Jupiter and RCW that is holding onto this Jupiter object. If there is, this Jupiter object and /// all dependent CCWs must be pegged. /// /// We typically report the AddRef *after* an AddRef and report the Release *before* a Release /// It's better to leak (temporarily) than crash. /// </summary> internal static void BeforeRelease(__ComObject comObject) { Debug.Assert(comObject.IsJupiterObject); __com_IJupiterObject* pJupiterObject = comObject.GetIJupiterObject_NoAddRef(); CalliIntrinsics.StdCall<int>(pJupiterObject->pVtable->pfnBeforeRelease, pJupiterObject); }
/// <summary> /// Reporting to Jupiter that we've done one AddRef to this object instance /// /// The ref count reporting is needed for Jupiter to determine whether there is something other than /// Jupiter and RCW that is holding onto this Jupiter object. If there is, this Jupiter object and /// all dependent CCWs must be pegged. /// /// We typically report the AddRef *after* an AddRef and report the Release *before* a Release /// It's better to leak (temporarily) than crash. /// </summary> internal static void AfterAddRef(__ComObject comObject) { Debug.Assert(comObject.IsJupiterObject); __com_IJupiterObject* pJupiterObject = comObject.GetIJupiterObject_NoAddRef(); // // Send out AfterAddRef callbacks to notify Jupiter we've done AddRef for certain interfaces // We should do this *after* we made a AddRef because we should never // be in a state where report refs > actual refs // CalliIntrinsics.StdCall<int>(pJupiterObject->pVtable->pfnAfterAddRef, pJupiterObject); }
/// <summary> /// Called after Jupiter RCW has been created /// </summary> internal static void AfterJupiterRCWCreated(__ComObject comObject) { __com_IJupiterObject* pJupiterObject = comObject.GetIJupiterObject_NoAddRef(); // // Notify Jupiter that we've created a new RCW for this Jupiter object // To avoid surprises, we should notify them before we fire the first AfterAddRef // CalliIntrinsics.StdCall<int>(pJupiterObject->pVtable->pfnConnect, pJupiterObject); // // Tell Jupiter that we've done AddRef for IJupiterObject* and IUnknown* // It's better to tell them later than earlier (prefering leaking than crashing) // AfterAddRef(comObject); AfterAddRef(comObject); }
/// <summary> /// Called when Jupiter RCW is being created /// We do one-time initialization for RCW walker here /// </summary> internal static void OnJupiterRCWCreated(__ComObject comObject) { Debug.Assert(comObject.IsJupiterObject); if (s_pGCManager == default(IntPtr)) { RCWWalker.Initialize(comObject.GetIJupiterObject_NoAddRef()); } }