//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.ComIntegration { using System; using System.Collections.Generic; using System.Runtime; using System.Runtime.InteropServices; using System.ServiceModel; class ProxyManager : IProxyManager { Dictionary InterfaceIDToComProxy; IProxyCreator proxyCreator; internal ProxyManager(IProxyCreator proxyCreator) { this.proxyCreator = proxyCreator; InterfaceIDToComProxy = new Dictionary(); } bool IsIntrinsic(ref Guid riid) { if ((riid == typeof(IChannelOptions).GUID) || (riid == typeof(IChannelCredentials).GUID) ) return true; return false; } void IProxyManager.TearDownChannels() { lock (this) { IEnumerator> enumeratorInterfaces = InterfaceIDToComProxy.GetEnumerator(); while (enumeratorInterfaces.MoveNext()) { KeyValuePair current = enumeratorInterfaces.Current; IDisposable comProxy = current.Value as IDisposable; if (comProxy == null) Fx.Assert("comProxy should not be null"); else comProxy.Dispose(); } InterfaceIDToComProxy.Clear(); proxyCreator.Dispose(); enumeratorInterfaces.Dispose(); proxyCreator = null; } } ComProxy CreateServiceChannel(IntPtr outerProxy, ref Guid riid) { return proxyCreator.CreateProxy(outerProxy, ref riid); } ComProxy GenerateIntrinsic(IntPtr outerProxy, ref Guid riid) { if (proxyCreator.SupportsIntrinsics()) { if (riid == typeof(IChannelOptions).GUID) return ChannelOptions.Create(outerProxy, proxyCreator as IProvideChannelBuilderSettings); else if (riid == typeof(IChannelCredentials).GUID) return ChannelCredentials.Create(outerProxy, proxyCreator as IProvideChannelBuilderSettings); else { throw Fx.AssertAndThrow("Given IID is not an intrinsic"); } } else { throw Fx.AssertAndThrow("proxyCreator does not support intrinsic"); } } void FindOrCreateProxyInternal(IntPtr outerProxy, ref Guid riid, out ComProxy comProxy) { comProxy = null; lock (this) { InterfaceIDToComProxy.TryGetValue(riid, out comProxy); if (comProxy == null) { if (IsIntrinsic(ref riid)) comProxy = GenerateIntrinsic(outerProxy, ref riid); else comProxy = CreateServiceChannel(outerProxy, ref riid); InterfaceIDToComProxy[riid] = comProxy; } } if (comProxy == null) { throw Fx.AssertAndThrow("comProxy should not be null at this point"); } } int IProxyManager.FindOrCreateProxy(IntPtr outerProxy, ref Guid riid, out IntPtr tearOff) { tearOff = IntPtr.Zero; try { ComProxy comProxy = null; FindOrCreateProxyInternal(outerProxy, ref riid, out comProxy); comProxy.QueryInterface(ref riid, out tearOff); return HR.S_OK; } catch (Exception e) { if (Fx.IsFatal(e)) throw; e = e.GetBaseException(); return Marshal.GetHRForException(e); } } int IProxyManager.InterfaceSupportsErrorInfo(ref Guid riid) { if (IsIntrinsic(ref riid)) return HR.S_OK; else return proxyCreator.SupportsErrorInfo(ref riid) ? HR.S_OK : HR.S_FALSE; } void IProxyManager.GetIDsOfNames( [MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr pDispID) { Int32 dispID = -1; switch (name) { case "ChannelOptions": dispID = 1; break; case "ChannelCredentials": dispID = 2; break; } Marshal.WriteInt32(pDispID, (int)dispID); } int IProxyManager.Invoke( UInt32 dispIdMember, IntPtr outerProxy, IntPtr pVarResult, IntPtr pExcepInfo ) { try { ComProxy comProxy = null; Guid riid; if ((dispIdMember == 1)) riid = typeof(IChannelOptions).GUID; else if ((dispIdMember == 2)) riid = typeof(IChannelCredentials).GUID; else return HR.DISP_E_MEMBERNOTFOUND; FindOrCreateProxyInternal(outerProxy, ref riid, out comProxy); TagVariant variant = new TagVariant(); variant.vt = (ushort)VarEnum.VT_DISPATCH; IntPtr tearOffDispatch = IntPtr.Zero; comProxy.QueryInterface(ref riid, out tearOffDispatch); variant.ptr = tearOffDispatch; Marshal.StructureToPtr(variant, pVarResult, true); return HR.S_OK; } catch (Exception e) { if (Fx.IsFatal(e)) throw; if (pExcepInfo != IntPtr.Zero) { System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO(); e = e.GetBaseException(); exceptionInfo.bstrDescription = e.Message; exceptionInfo.bstrSource = e.Source; exceptionInfo.scode = Marshal.GetHRForException(e); Marshal.StructureToPtr(exceptionInfo, pExcepInfo, false); } return HR.DISP_E_EXCEPTION; } } int IProxyManager.SupportsDispatch() { if (proxyCreator.SupportsDispatch()) return HR.S_OK; else return HR.E_FAIL; } } }