SqlDataSourceEnumerator.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlDataSourceEnumerator.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">Microsoft</owner>
  6. // <owner current="true" primary="false">Microsoft</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data.Sql {
  9. using System;
  10. using System.Data;
  11. using System.Data.Common;
  12. using System.Data.SqlClient;
  13. using System.Diagnostics;
  14. using System.Globalization;
  15. using System.Runtime.CompilerServices;
  16. using System.Runtime.InteropServices;
  17. using System.Security;
  18. using System.Text;
  19. public sealed class SqlDataSourceEnumerator : DbDataSourceEnumerator {
  20. private static readonly SqlDataSourceEnumerator SingletonInstance = new SqlDataSourceEnumerator();
  21. internal const string ServerName = "ServerName";
  22. internal const string InstanceName = "InstanceName";
  23. internal const string IsClustered = "IsClustered";
  24. internal const string Version = "Version";
  25. #if !MONO
  26. private const int timeoutSeconds = ADP.DefaultCommandTimeout;
  27. #endif
  28. private long timeoutTime; // variable used for timeout computations, holds the value of the hi-res performance counter at which this request should expire
  29. private SqlDataSourceEnumerator() : base() {
  30. }
  31. public static SqlDataSourceEnumerator Instance {
  32. get {
  33. return SqlDataSourceEnumerator.SingletonInstance;
  34. }
  35. }
  36. override public DataTable GetDataSources() {
  37. #if MONO
  38. timeoutTime = 0;
  39. throw new NotImplementedException ();
  40. #else
  41. (new NamedPermissionSet("FullTrust")).Demand(); // SQLBUDT 244304
  42. char[] buffer = null;
  43. StringBuilder strbldr = new StringBuilder();
  44. Int32 bufferSize = 1024;
  45. Int32 readLength = 0;
  46. buffer = new char[bufferSize];
  47. bool more = true;
  48. bool failure = false;
  49. IntPtr handle = ADP.PtrZero;
  50. RuntimeHelpers.PrepareConstrainedRegions();
  51. try {
  52. timeoutTime = TdsParserStaticMethods.GetTimeoutSeconds(timeoutSeconds);
  53. RuntimeHelpers.PrepareConstrainedRegions();
  54. try {} finally {
  55. handle = SNINativeMethodWrapper.SNIServerEnumOpen();
  56. }
  57. if (ADP.PtrZero != handle) {
  58. while (more && !TdsParserStaticMethods.TimeoutHasExpired(timeoutTime)) {
  59. readLength = SNINativeMethodWrapper.SNIServerEnumRead(handle, buffer, bufferSize, ref more);
  60. if (readLength > bufferSize) {
  61. failure = true;
  62. more = false;
  63. }
  64. else if (0 < readLength) {
  65. strbldr.Append(buffer, 0, readLength);
  66. }
  67. }
  68. }
  69. }
  70. finally {
  71. if (ADP.PtrZero != handle) {
  72. SNINativeMethodWrapper.SNIServerEnumClose(handle);
  73. }
  74. }
  75. if (failure) {
  76. Debug.Assert(false, "GetDataSources:SNIServerEnumRead returned bad length");
  77. Bid.Trace("<sc.SqlDataSourceEnumerator.GetDataSources|ERR> GetDataSources:SNIServerEnumRead returned bad length, requested %d, received %d", bufferSize, readLength);
  78. throw ADP.ArgumentOutOfRange("readLength");
  79. }
  80. return ParseServerEnumString(strbldr.ToString());
  81. #endif
  82. }
  83. private static string _Version = "Version:";
  84. private static string _Cluster = "Clustered:";
  85. private static int _clusterLength = _Cluster.Length;
  86. private static int _versionLength =_Version.Length;
  87. static private DataTable ParseServerEnumString(string serverInstances) {
  88. DataTable dataTable = new DataTable("SqlDataSources");
  89. dataTable.Locale = CultureInfo.InvariantCulture;
  90. dataTable.Columns.Add(ServerName, typeof(string));
  91. dataTable.Columns.Add(InstanceName, typeof(string));
  92. dataTable.Columns.Add(IsClustered, typeof(string));
  93. dataTable.Columns.Add(Version, typeof(string));
  94. DataRow dataRow = null;
  95. string serverName = null;
  96. string instanceName = null;
  97. string isClustered = null;
  98. string version = null;
  99. // Every row comes in the format "serverName\instanceName;Clustered:[Yes|No];Version:.."
  100. // Every row is terminated by a null character.
  101. // Process one row at a time
  102. foreach (string instance in serverInstances.Split('\0')) {
  103. string value = instance.Trim('\0'); // MDAC 91934
  104. if (0 == value.Length) {
  105. continue;
  106. }
  107. foreach (string instance2 in value.Split(';')) {
  108. if (serverName == null) {
  109. foreach(string instance3 in instance2.Split('\\')) {
  110. if (serverName == null) {
  111. serverName = instance3;
  112. continue;
  113. }
  114. Debug.Assert(instanceName == null);
  115. instanceName = instance3;
  116. }
  117. continue;
  118. }
  119. if (isClustered == null) {
  120. Debug.Assert(String.Compare(_Cluster, 0, instance2, 0, _clusterLength, StringComparison.OrdinalIgnoreCase) == 0);
  121. isClustered = instance2.Substring(_clusterLength);
  122. continue;
  123. }
  124. Debug.Assert(version == null);
  125. Debug.Assert(String.Compare(_Version, 0, instance2, 0, _versionLength, StringComparison.OrdinalIgnoreCase) == 0);
  126. version = instance2.Substring(_versionLength);
  127. }
  128. string query = "ServerName='"+serverName+"'";
  129. if (!ADP.IsEmpty(instanceName)) { // SQL BU DT 20006584: only append instanceName if present.
  130. query += " AND InstanceName='"+instanceName+"'";
  131. }
  132. // SNI returns dupes - do not add them. SQL BU DT 290323
  133. if (dataTable.Select(query).Length == 0) {
  134. dataRow = dataTable.NewRow();
  135. dataRow[0] = serverName;
  136. dataRow[1] = instanceName;
  137. dataRow[2] = isClustered;
  138. dataRow[3] = version;
  139. dataTable.Rows.Add(dataRow);
  140. }
  141. serverName = null;
  142. instanceName = null;
  143. isClustered = null;
  144. version = null;
  145. }
  146. foreach(DataColumn column in dataTable.Columns) {
  147. column.ReadOnly = true;
  148. }
  149. return dataTable;
  150. }
  151. }
  152. }