ProxyManager.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.ComIntegration
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Runtime;
  9. using System.Runtime.InteropServices;
  10. using System.ServiceModel;
  11. class ProxyManager : IProxyManager
  12. {
  13. Dictionary<Guid, ComProxy> InterfaceIDToComProxy;
  14. IProxyCreator proxyCreator;
  15. internal ProxyManager(IProxyCreator proxyCreator)
  16. {
  17. this.proxyCreator = proxyCreator;
  18. InterfaceIDToComProxy = new Dictionary<Guid, ComProxy>();
  19. }
  20. bool IsIntrinsic(ref Guid riid)
  21. {
  22. if ((riid == typeof(IChannelOptions).GUID)
  23. ||
  24. (riid == typeof(IChannelCredentials).GUID)
  25. )
  26. return true;
  27. return false;
  28. }
  29. void IProxyManager.TearDownChannels()
  30. {
  31. lock (this)
  32. {
  33. IEnumerator<KeyValuePair<Guid, ComProxy>> enumeratorInterfaces = InterfaceIDToComProxy.GetEnumerator();
  34. while (enumeratorInterfaces.MoveNext())
  35. {
  36. KeyValuePair<Guid, ComProxy> current = enumeratorInterfaces.Current;
  37. IDisposable comProxy = current.Value as IDisposable;
  38. if (comProxy == null)
  39. Fx.Assert("comProxy should not be null");
  40. else
  41. comProxy.Dispose();
  42. }
  43. InterfaceIDToComProxy.Clear();
  44. proxyCreator.Dispose();
  45. enumeratorInterfaces.Dispose();
  46. proxyCreator = null;
  47. }
  48. }
  49. ComProxy CreateServiceChannel(IntPtr outerProxy, ref Guid riid)
  50. {
  51. return proxyCreator.CreateProxy(outerProxy, ref riid);
  52. }
  53. ComProxy GenerateIntrinsic(IntPtr outerProxy, ref Guid riid)
  54. {
  55. if (proxyCreator.SupportsIntrinsics())
  56. {
  57. if (riid == typeof(IChannelOptions).GUID)
  58. return ChannelOptions.Create(outerProxy, proxyCreator as IProvideChannelBuilderSettings);
  59. else if (riid == typeof(IChannelCredentials).GUID)
  60. return ChannelCredentials.Create(outerProxy, proxyCreator as IProvideChannelBuilderSettings);
  61. else
  62. {
  63. throw Fx.AssertAndThrow("Given IID is not an intrinsic");
  64. }
  65. }
  66. else
  67. {
  68. throw Fx.AssertAndThrow("proxyCreator does not support intrinsic");
  69. }
  70. }
  71. void FindOrCreateProxyInternal(IntPtr outerProxy, ref Guid riid, out ComProxy comProxy)
  72. {
  73. comProxy = null;
  74. lock (this)
  75. {
  76. InterfaceIDToComProxy.TryGetValue(riid, out comProxy);
  77. if (comProxy == null)
  78. {
  79. if (IsIntrinsic(ref riid))
  80. comProxy = GenerateIntrinsic(outerProxy, ref riid);
  81. else
  82. comProxy = CreateServiceChannel(outerProxy, ref riid);
  83. InterfaceIDToComProxy[riid] = comProxy;
  84. }
  85. }
  86. if (comProxy == null)
  87. {
  88. throw Fx.AssertAndThrow("comProxy should not be null at this point");
  89. }
  90. }
  91. int IProxyManager.FindOrCreateProxy(IntPtr outerProxy, ref Guid riid, out IntPtr tearOff)
  92. {
  93. tearOff = IntPtr.Zero;
  94. try
  95. {
  96. ComProxy comProxy = null;
  97. FindOrCreateProxyInternal(outerProxy, ref riid, out comProxy);
  98. comProxy.QueryInterface(ref riid, out tearOff);
  99. return HR.S_OK;
  100. }
  101. catch (Exception e)
  102. {
  103. if (Fx.IsFatal(e))
  104. throw;
  105. e = e.GetBaseException();
  106. return Marshal.GetHRForException(e);
  107. }
  108. }
  109. int IProxyManager.InterfaceSupportsErrorInfo(ref Guid riid)
  110. {
  111. if (IsIntrinsic(ref riid))
  112. return HR.S_OK;
  113. else
  114. return proxyCreator.SupportsErrorInfo(ref riid) ? HR.S_OK : HR.S_FALSE;
  115. }
  116. void IProxyManager.GetIDsOfNames(
  117. [MarshalAs(UnmanagedType.LPWStr)] string name,
  118. IntPtr pDispID)
  119. {
  120. Int32 dispID = -1;
  121. switch (name)
  122. {
  123. case "ChannelOptions":
  124. dispID = 1;
  125. break;
  126. case "ChannelCredentials":
  127. dispID = 2;
  128. break;
  129. }
  130. Marshal.WriteInt32(pDispID, (int)dispID);
  131. }
  132. int IProxyManager.Invoke(
  133. UInt32 dispIdMember,
  134. IntPtr outerProxy,
  135. IntPtr pVarResult,
  136. IntPtr pExcepInfo
  137. )
  138. {
  139. try
  140. {
  141. ComProxy comProxy = null;
  142. Guid riid;
  143. if ((dispIdMember == 1))
  144. riid = typeof(IChannelOptions).GUID;
  145. else if ((dispIdMember == 2))
  146. riid = typeof(IChannelCredentials).GUID;
  147. else
  148. return HR.DISP_E_MEMBERNOTFOUND;
  149. FindOrCreateProxyInternal(outerProxy, ref riid, out comProxy);
  150. TagVariant variant = new TagVariant();
  151. variant.vt = (ushort)VarEnum.VT_DISPATCH;
  152. IntPtr tearOffDispatch = IntPtr.Zero;
  153. comProxy.QueryInterface(ref riid, out tearOffDispatch);
  154. variant.ptr = tearOffDispatch;
  155. Marshal.StructureToPtr(variant, pVarResult, true);
  156. return HR.S_OK;
  157. }
  158. catch (Exception e)
  159. {
  160. if (Fx.IsFatal(e))
  161. throw;
  162. if (pExcepInfo != IntPtr.Zero)
  163. {
  164. System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();
  165. e = e.GetBaseException();
  166. exceptionInfo.bstrDescription = e.Message;
  167. exceptionInfo.bstrSource = e.Source;
  168. exceptionInfo.scode = Marshal.GetHRForException(e);
  169. Marshal.StructureToPtr(exceptionInfo, pExcepInfo, false);
  170. }
  171. return HR.DISP_E_EXCEPTION;
  172. }
  173. }
  174. int IProxyManager.SupportsDispatch()
  175. {
  176. if (proxyCreator.SupportsDispatch())
  177. return HR.S_OK;
  178. else
  179. return HR.E_FAIL;
  180. }
  181. }
  182. }