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