ServiceInfo.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.ComIntegration
  5. {
  6. using System;
  7. using System.ServiceModel.Dispatcher;
  8. using System.ServiceModel.Description;
  9. using System.Collections.Generic;
  10. using System.Collections;
  11. using System.Diagnostics;
  12. using System.EnterpriseServices;
  13. using System.Reflection;
  14. using System.Runtime.InteropServices;
  15. using System.ServiceModel;
  16. using System.ServiceModel.Configuration;
  17. using System.Transactions;
  18. using SR = System.ServiceModel.SR;
  19. using System.ServiceModel.Diagnostics;
  20. using System.Runtime;
  21. // The values of the enum are reflected from the values in the
  22. // COM+ Admin SDK.
  23. //
  24. enum Bitness
  25. {
  26. Bitness32 = 0x01,
  27. Bitness64 = 0x02
  28. }
  29. enum ThreadingModel
  30. {
  31. MTA,
  32. STA
  33. }
  34. enum HostingMode
  35. {
  36. ComPlus, // Living in a DllHost.exe
  37. WebHostOutOfProcess, // From webhost to dllhost.exe
  38. WebHostInProcess // Inside webhost
  39. }
  40. class ServiceInfo
  41. {
  42. ServiceElement service;
  43. Guid clsid;
  44. Guid appid;
  45. HostingMode hostingMode;
  46. Guid partitionId;
  47. Bitness bitness;
  48. ThreadingModel threadingModel;
  49. TransactionOption transactionOption;
  50. IsolationLevel isolationLevel;
  51. bool checkRoles;
  52. string[] componentRoleMembers;
  53. bool objectPoolingEnabled;
  54. int maxPoolSize;
  55. Type managedType;
  56. List<ContractInfo> contracts;
  57. string serviceName;
  58. Dictionary<Guid, List<Type>> udts;
  59. public string ServiceName
  60. {
  61. get
  62. {
  63. return serviceName;
  64. }
  65. }
  66. // NOTE: Construction of this thing is quite inefficient-- it
  67. // has several nested loops that could probably be
  68. // improved. Such optimizations have been left for when
  69. // it turns out to be a performance problem, for the
  70. // sake of simplicity.
  71. //
  72. public ServiceInfo(Guid clsid,
  73. ServiceElement service,
  74. ComCatalogObject application,
  75. ComCatalogObject classObject,
  76. HostingMode hostingMode)
  77. {
  78. // Simple things...
  79. //
  80. this.service = service;
  81. this.clsid = clsid;
  82. this.appid = Fx.CreateGuid((string)application.GetValue("ID"));
  83. this.partitionId = Fx.CreateGuid((string)application.GetValue("AppPartitionID"));
  84. this.bitness = (Bitness)classObject.GetValue("Bitness");
  85. this.transactionOption = (TransactionOption)classObject.GetValue("Transaction");
  86. this.hostingMode = hostingMode;
  87. this.managedType = TypeCacheManager.ResolveClsidToType(clsid);
  88. this.serviceName = application.Name + "." + classObject.Name;
  89. this.udts = new Dictionary<Guid, List<Type>>();
  90. // Isolation Level
  91. COMAdminIsolationLevel adminIsolationLevel;
  92. adminIsolationLevel = (COMAdminIsolationLevel)classObject.GetValue("TxIsolationLevel");
  93. switch (adminIsolationLevel)
  94. {
  95. case COMAdminIsolationLevel.Any:
  96. this.isolationLevel = IsolationLevel.Unspecified;
  97. break;
  98. case COMAdminIsolationLevel.ReadUncommitted:
  99. this.isolationLevel = IsolationLevel.ReadUncommitted;
  100. break;
  101. case COMAdminIsolationLevel.ReadCommitted:
  102. this.isolationLevel = IsolationLevel.ReadCommitted;
  103. break;
  104. case COMAdminIsolationLevel.RepeatableRead:
  105. this.isolationLevel = IsolationLevel.RepeatableRead;
  106. break;
  107. case COMAdminIsolationLevel.Serializable:
  108. this.isolationLevel = IsolationLevel.Serializable;
  109. break;
  110. default:
  111. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
  112. SR.GetString(SR.InvalidIsolationLevelValue,
  113. this.clsid, adminIsolationLevel)));
  114. }
  115. // Threading Model
  116. //
  117. COMAdminThreadingModel adminThreadingModel;
  118. adminThreadingModel = (COMAdminThreadingModel)classObject.GetValue("ThreadingModel");
  119. switch (adminThreadingModel)
  120. {
  121. case COMAdminThreadingModel.Apartment:
  122. case COMAdminThreadingModel.Main:
  123. this.threadingModel = ThreadingModel.STA;
  124. objectPoolingEnabled = false;
  125. break;
  126. default:
  127. this.threadingModel = ThreadingModel.MTA;
  128. objectPoolingEnabled = (bool)classObject.GetValue("ObjectPoolingEnabled");
  129. break;
  130. }
  131. // Object Pool settings
  132. //
  133. if (objectPoolingEnabled)
  134. {
  135. maxPoolSize = (int)classObject.GetValue("MaxPoolSize");
  136. }
  137. else
  138. maxPoolSize = 0;
  139. // Security Settings
  140. //
  141. bool appSecurityEnabled;
  142. appSecurityEnabled = (bool)application.GetValue(
  143. "ApplicationAccessChecksEnabled");
  144. if (appSecurityEnabled)
  145. {
  146. bool classSecurityEnabled;
  147. classSecurityEnabled = (bool)classObject.GetValue(
  148. "ComponentAccessChecksEnabled");
  149. if (classSecurityEnabled)
  150. {
  151. this.checkRoles = true;
  152. }
  153. }
  154. // Component Roles
  155. //
  156. ComCatalogCollection roles;
  157. roles = classObject.GetCollection("RolesForComponent");
  158. this.componentRoleMembers = CatalogUtil.GetRoleMembers(application, roles);
  159. // Contracts
  160. // One ContractInfo per unique IID exposed, so we need to
  161. // filter duplicates.
  162. //
  163. this.contracts = new List<ContractInfo>();
  164. ComCatalogCollection interfaces;
  165. interfaces = classObject.GetCollection("InterfacesForComponent");
  166. foreach (ServiceEndpointElement endpoint in service.Endpoints)
  167. {
  168. ContractInfo contract = null;
  169. if (endpoint.Contract == ServiceMetadataBehavior.MexContractName)
  170. continue;
  171. Guid iid;
  172. if (DiagnosticUtility.Utility.TryCreateGuid(endpoint.Contract, out iid))
  173. {
  174. // (Filter duplicates.)
  175. bool duplicate = false;
  176. foreach (ContractInfo otherContract in this.contracts)
  177. {
  178. if (iid == otherContract.IID)
  179. {
  180. duplicate = true;
  181. break;
  182. }
  183. }
  184. if (duplicate) continue;
  185. foreach (ComCatalogObject interfaceObject in interfaces)
  186. {
  187. Guid otherInterfaceID;
  188. if (DiagnosticUtility.Utility.TryCreateGuid((string)interfaceObject.GetValue("IID"), out otherInterfaceID))
  189. {
  190. if (otherInterfaceID == iid)
  191. {
  192. contract = new ContractInfo(iid,
  193. endpoint,
  194. interfaceObject,
  195. application);
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. if (contract == null)
  202. {
  203. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(
  204. SR.GetString(SR.EndpointNotAnIID,
  205. clsid.ToString("B").ToUpperInvariant(),
  206. endpoint.Contract)));
  207. }
  208. this.contracts.Add(contract);
  209. }
  210. }
  211. public Type ServiceType
  212. {
  213. get { return this.managedType; }
  214. }
  215. public ServiceElement ServiceElement
  216. {
  217. get { return this.service; }
  218. }
  219. public Guid Clsid
  220. {
  221. get { return this.clsid; }
  222. }
  223. public Guid AppID
  224. {
  225. get { return this.appid; }
  226. }
  227. public Guid PartitionId
  228. {
  229. get { return this.partitionId; }
  230. }
  231. public Bitness Bitness
  232. {
  233. get { return this.bitness; }
  234. }
  235. public bool CheckRoles
  236. {
  237. get { return this.checkRoles; }
  238. }
  239. public ThreadingModel ThreadingModel
  240. {
  241. get { return this.threadingModel; }
  242. }
  243. public TransactionOption TransactionOption
  244. {
  245. get { return this.transactionOption; }
  246. }
  247. public IsolationLevel IsolationLevel
  248. {
  249. get { return this.isolationLevel; }
  250. }
  251. public string[] ComponentRoleMembers
  252. {
  253. get { return this.componentRoleMembers; }
  254. }
  255. public List<ContractInfo> Contracts
  256. {
  257. get { return this.contracts; }
  258. }
  259. public HostingMode HostingMode
  260. {
  261. get { return this.hostingMode; }
  262. }
  263. public bool Pooled
  264. {
  265. get { return this.objectPoolingEnabled; }
  266. }
  267. public int MaxPoolSize
  268. {
  269. get { return this.maxPoolSize; }
  270. }
  271. internal Guid[] Assemblies
  272. {
  273. get
  274. {
  275. Guid[] ret = new Guid[this.udts.Keys.Count];
  276. this.udts.Keys.CopyTo(ret, 0);
  277. return ret;
  278. }
  279. }
  280. internal bool HasUdts()
  281. {
  282. // use the assembly count since we only add assemblies when we got UDTs
  283. return (this.udts.Keys.Count > 0);
  284. }
  285. internal Type[] GetTypes(Guid assemblyId)
  286. {
  287. List<Type> ret = null;
  288. udts.TryGetValue(assemblyId, out ret);
  289. if (null == ret)
  290. return new Type[0];
  291. return ret.ToArray();
  292. }
  293. internal void AddUdt(Type udt, Guid assemblyId)
  294. {
  295. if (!udts.ContainsKey(assemblyId))
  296. udts[assemblyId] = new List<Type>();
  297. if (!udts[assemblyId].Contains(udt))
  298. udts[assemblyId].Add(udt);
  299. }
  300. }
  301. class ContractInfo
  302. {
  303. string name;
  304. Guid iid;
  305. string[] interfaceRoleMembers;
  306. List<OperationInfo> operations;
  307. public ContractInfo(Guid iid,
  308. ServiceEndpointElement endpoint,
  309. ComCatalogObject interfaceObject,
  310. ComCatalogObject application)
  311. {
  312. this.name = endpoint.Contract;
  313. this.iid = iid;
  314. // Interface Roles
  315. //
  316. ComCatalogCollection roles;
  317. roles = interfaceObject.GetCollection("RolesForInterface");
  318. this.interfaceRoleMembers = CatalogUtil.GetRoleMembers(application,
  319. roles);
  320. // Operations
  321. //
  322. this.operations = new List<OperationInfo>();
  323. ComCatalogCollection methods;
  324. methods = interfaceObject.GetCollection("MethodsForInterface");
  325. foreach (ComCatalogObject method in methods)
  326. {
  327. this.operations.Add(new OperationInfo(method,
  328. application));
  329. }
  330. }
  331. public string Name
  332. {
  333. get { return this.name; }
  334. }
  335. public Guid IID
  336. {
  337. get { return this.iid; }
  338. }
  339. public string[] InterfaceRoleMembers
  340. {
  341. get { return this.interfaceRoleMembers; }
  342. }
  343. public List<OperationInfo> Operations
  344. {
  345. get { return this.operations; }
  346. }
  347. }
  348. class OperationInfo
  349. {
  350. string name;
  351. string[] methodRoleMembers;
  352. public OperationInfo(ComCatalogObject methodObject,
  353. ComCatalogObject application)
  354. {
  355. this.name = (string)methodObject.GetValue("Name");
  356. // Method Roles
  357. //
  358. ComCatalogCollection roles;
  359. roles = methodObject.GetCollection("RolesForMethod");
  360. this.methodRoleMembers = CatalogUtil.GetRoleMembers(application,
  361. roles);
  362. }
  363. public string Name
  364. {
  365. get { return this.name; }
  366. }
  367. public string[] MethodRoleMembers
  368. {
  369. get { return this.methodRoleMembers; }
  370. }
  371. }
  372. }