SqlConnectionString.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlConnectionString.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data.SqlClient {
  9. using System;
  10. using System.Collections;
  11. using System.Data;
  12. using System.Data.Common;
  13. using System.Diagnostics;
  14. using System.Globalization;
  15. using System.IO;
  16. using System.Security;
  17. using System.Security.Permissions;
  18. using System.Text;
  19. using System.Runtime.Versioning;
  20. internal sealed class SqlConnectionString : DbConnectionOptions {
  21. // instances of this class are intended to be immutable, i.e readonly
  22. // used by pooling classes so it is much easier to verify correctness
  23. // when not worried about the class being modified during execution
  24. internal static class DEFAULT {
  25. internal const ApplicationIntent ApplicationIntent = DbConnectionStringDefaults.ApplicationIntent;
  26. internal const string Application_Name = TdsEnums.SQL_PROVIDER_NAME;
  27. internal const bool Asynchronous = false;
  28. internal const string AttachDBFilename = "";
  29. internal const int Connect_Timeout = ADP.DefaultConnectionTimeout;
  30. internal const bool Connection_Reset = true;
  31. internal const bool Context_Connection = false;
  32. internal const string Current_Language = "";
  33. internal const string Data_Source = "";
  34. internal const bool Encrypt = false;
  35. internal const bool Enlist = true;
  36. internal const string FailoverPartner = "";
  37. internal const string Initial_Catalog = "";
  38. internal const bool Integrated_Security = false;
  39. internal const int Load_Balance_Timeout = 0; // default of 0 means don't use
  40. internal const bool MARS = false;
  41. internal const int Max_Pool_Size = 100;
  42. internal const int Min_Pool_Size = 0;
  43. internal const bool MultiSubnetFailover = DbConnectionStringDefaults.MultiSubnetFailover;
  44. internal const string Network_Library = "";
  45. internal const int Packet_Size = 8000;
  46. internal const string Password = "";
  47. internal const bool Persist_Security_Info = false;
  48. internal const bool Pooling = true;
  49. internal const bool TrustServerCertificate = false;
  50. internal const string Type_System_Version = "";
  51. internal const string User_ID = "";
  52. internal const bool User_Instance = false;
  53. internal const bool Replication = false;
  54. internal const int Connect_Retry_Count = 1;
  55. internal const int Connect_Retry_Interval = 10;
  56. }
  57. // SqlConnection ConnectionString Options
  58. // keys must be lowercase!
  59. internal static class KEY {
  60. internal const string ApplicationIntent = "applicationintent";
  61. internal const string Application_Name = "application name";
  62. internal const string AsynchronousProcessing = "asynchronous processing";
  63. internal const string AttachDBFilename = "attachdbfilename";
  64. internal const string Connect_Timeout = "connect timeout";
  65. internal const string Connection_Reset = "connection reset";
  66. internal const string Context_Connection = "context connection";
  67. internal const string Current_Language = "current language";
  68. internal const string Data_Source = "data source";
  69. internal const string Encrypt = "encrypt";
  70. internal const string Enlist = "enlist";
  71. internal const string FailoverPartner = "failover partner";
  72. internal const string Initial_Catalog = "initial catalog";
  73. internal const string Integrated_Security = "integrated security";
  74. internal const string Load_Balance_Timeout = "load balance timeout";
  75. internal const string MARS = "multipleactiveresultsets";
  76. internal const string Max_Pool_Size = "max pool size";
  77. internal const string Min_Pool_Size = "min pool size";
  78. internal const string MultiSubnetFailover = "multisubnetfailover";
  79. internal const string Network_Library = "network library";
  80. internal const string Packet_Size = "packet size";
  81. internal const string Password = "password";
  82. internal const string Persist_Security_Info = "persist security info";
  83. internal const string Pooling = "pooling";
  84. internal const string TransactionBinding = "transaction binding";
  85. internal const string TrustServerCertificate = "trustservercertificate";
  86. internal const string Type_System_Version = "type system version";
  87. internal const string User_ID = "user id";
  88. internal const string User_Instance = "user instance";
  89. internal const string Workstation_Id = "workstation id";
  90. internal const string Replication = "replication";
  91. internal const string Connect_Retry_Count = "connectretrycount";
  92. internal const string Connect_Retry_Interval = "connectretryinterval";
  93. }
  94. // Constant for the number of duplicate options in the connnection string
  95. private static class SYNONYM {
  96. // application name
  97. internal const string APP = "app";
  98. internal const string Async = "async";
  99. // attachDBFilename
  100. internal const string EXTENDED_PROPERTIES = "extended properties";
  101. internal const string INITIAL_FILE_NAME = "initial file name";
  102. // connect timeout
  103. internal const string CONNECTION_TIMEOUT = "connection timeout";
  104. internal const string TIMEOUT = "timeout";
  105. // current language
  106. internal const string LANGUAGE = "language";
  107. // data source
  108. internal const string ADDR = "addr";
  109. internal const string ADDRESS = "address";
  110. internal const string SERVER = "server";
  111. internal const string NETWORK_ADDRESS = "network address";
  112. // initial catalog
  113. internal const string DATABASE = "database";
  114. // integrated security
  115. internal const string TRUSTED_CONNECTION = "trusted_connection";
  116. // load balance timeout
  117. internal const string Connection_Lifetime = "connection lifetime";
  118. // network library
  119. internal const string NET = "net";
  120. internal const string NETWORK = "network";
  121. // password
  122. internal const string Pwd = "pwd";
  123. // persist security info
  124. internal const string PERSISTSECURITYINFO = "persistsecurityinfo";
  125. // user id
  126. internal const string UID = "uid";
  127. internal const string User = "user";
  128. // workstation id
  129. internal const string WSID = "wsid";
  130. // make sure to update SynonymCount value below when adding or removing synonyms
  131. }
  132. internal const int SynonymCount = 21;
  133. // the following are all inserted as keys into the _netlibMapping hash
  134. internal static class NETLIB {
  135. internal const string AppleTalk = "dbmsadsn";
  136. internal const string BanyanVines = "dbmsvinn";
  137. internal const string IPXSPX = "dbmsspxn";
  138. internal const string Multiprotocol = "dbmsrpcn";
  139. internal const string NamedPipes = "dbnmpntw";
  140. internal const string SharedMemory = "dbmslpcn";
  141. internal const string TCPIP = "dbmssocn";
  142. internal const string VIA = "dbmsgnet";
  143. }
  144. internal enum TypeSystem {
  145. Latest = 2008,
  146. SQLServer2000 = 2000,
  147. SQLServer2005 = 2005,
  148. SQLServer2008 = 2008,
  149. SQLServer2012 = 2012,
  150. }
  151. internal static class TYPESYSTEMVERSION {
  152. internal const string Latest = "Latest";
  153. internal const string SQL_Server_2000 = "SQL Server 2000";
  154. internal const string SQL_Server_2005 = "SQL Server 2005";
  155. internal const string SQL_Server_2008 = "SQL Server 2008";
  156. internal const string SQL_Server_2012 = "SQL Server 2012";
  157. }
  158. internal enum TransactionBindingEnum {
  159. ImplicitUnbind,
  160. ExplicitUnbind
  161. }
  162. internal static class TRANSACIONBINDING {
  163. internal const string ImplicitUnbind = "Implicit Unbind";
  164. internal const string ExplicitUnbind = "Explicit Unbind";
  165. }
  166. static private Hashtable _sqlClientSynonyms;
  167. static private Hashtable _netlibMapping;
  168. private readonly bool _integratedSecurity;
  169. private readonly bool _connectionReset;
  170. private readonly bool _contextConnection;
  171. private readonly bool _encrypt;
  172. private readonly bool _trustServerCertificate;
  173. private readonly bool _enlist;
  174. private readonly bool _mars;
  175. private readonly bool _persistSecurityInfo;
  176. private readonly bool _pooling;
  177. private readonly bool _replication;
  178. private readonly bool _userInstance;
  179. private readonly bool _multiSubnetFailover;
  180. private readonly int _connectTimeout;
  181. private readonly int _loadBalanceTimeout;
  182. private readonly int _maxPoolSize;
  183. private readonly int _minPoolSize;
  184. private readonly int _packetSize;
  185. private readonly int _connectRetryCount;
  186. private readonly int _connectRetryInterval;
  187. private readonly ApplicationIntent _applicationIntent;
  188. private readonly string _applicationName;
  189. private readonly string _attachDBFileName;
  190. private readonly string _currentLanguage;
  191. private readonly string _dataSource;
  192. private readonly string _localDBInstance; // created based on datasource, set to NULL if datasource is not LocalDB
  193. private readonly string _failoverPartner;
  194. private readonly string _initialCatalog;
  195. private readonly string _password;
  196. private readonly string _userID;
  197. private readonly string _networkLibrary;
  198. private readonly string _workstationId;
  199. private readonly TypeSystem _typeSystemVersion;
  200. private readonly Version _typeSystemAssemblyVersion;
  201. private static readonly Version constTypeSystemAsmVersion10 = new Version("10.0.0.0");
  202. private static readonly Version constTypeSystemAsmVersion11 = new Version("11.0.0.0");
  203. private readonly TransactionBindingEnum _transactionBinding;
  204. private readonly string _expandedAttachDBFilename; // expanded during construction so that CreatePermissionSet & Expand are consistent
  205. // SxS: reading Software\\Microsoft\\MSSQLServer\\Client\\SuperSocketNetLib\Encrypt value from registry
  206. [ResourceExposure(ResourceScope.None)]
  207. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  208. internal SqlConnectionString(string connectionString) : base(connectionString, GetParseSynonyms(), false) {
  209. bool runningInProc = InOutOfProcHelper.InProc;
  210. _integratedSecurity = ConvertValueToIntegratedSecurity();
  211. ConvertValueToBoolean(KEY.AsynchronousProcessing, DEFAULT.Asynchronous); // while we don't use it anymore, we still need to verify it is true/false
  212. // SQLPT 41700: Ignore ResetConnection=False (still validate the keyword/value)
  213. _connectionReset = ConvertValueToBoolean(KEY.Connection_Reset, DEFAULT.Connection_Reset);
  214. _contextConnection = ConvertValueToBoolean(KEY.Context_Connection, DEFAULT.Context_Connection);
  215. _encrypt = ConvertValueToBoolean(KEY.Encrypt, DEFAULT.Encrypt);
  216. _enlist = ConvertValueToBoolean(KEY.Enlist, ADP.IsWindowsNT);
  217. _mars = ConvertValueToBoolean(KEY.MARS, DEFAULT.MARS);
  218. _persistSecurityInfo = ConvertValueToBoolean(KEY.Persist_Security_Info, DEFAULT.Persist_Security_Info);
  219. _pooling = ConvertValueToBoolean(KEY.Pooling, DEFAULT.Pooling);
  220. _replication = ConvertValueToBoolean(KEY.Replication, DEFAULT.Replication);
  221. _userInstance = ConvertValueToBoolean(KEY.User_Instance, DEFAULT.User_Instance);
  222. _multiSubnetFailover = ConvertValueToBoolean(KEY.MultiSubnetFailover, DEFAULT.MultiSubnetFailover);
  223. _connectTimeout = ConvertValueToInt32(KEY.Connect_Timeout, DEFAULT.Connect_Timeout);
  224. _loadBalanceTimeout = ConvertValueToInt32(KEY.Load_Balance_Timeout, DEFAULT.Load_Balance_Timeout);
  225. _maxPoolSize = ConvertValueToInt32(KEY.Max_Pool_Size, DEFAULT.Max_Pool_Size);
  226. _minPoolSize = ConvertValueToInt32(KEY.Min_Pool_Size, DEFAULT.Min_Pool_Size);
  227. _packetSize = ConvertValueToInt32(KEY.Packet_Size, DEFAULT.Packet_Size);
  228. _connectRetryCount = ConvertValueToInt32(KEY.Connect_Retry_Count, DEFAULT.Connect_Retry_Count);
  229. _connectRetryInterval = ConvertValueToInt32(KEY.Connect_Retry_Interval, DEFAULT.Connect_Retry_Interval);
  230. _applicationIntent = ConvertValueToApplicationIntent();
  231. _applicationName = ConvertValueToString(KEY.Application_Name, DEFAULT.Application_Name);
  232. _attachDBFileName = ConvertValueToString(KEY.AttachDBFilename, DEFAULT.AttachDBFilename);
  233. _currentLanguage = ConvertValueToString(KEY.Current_Language, DEFAULT.Current_Language);
  234. _dataSource = ConvertValueToString(KEY.Data_Source, DEFAULT.Data_Source);
  235. _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
  236. _failoverPartner = ConvertValueToString(KEY.FailoverPartner, DEFAULT.FailoverPartner);
  237. _initialCatalog = ConvertValueToString(KEY.Initial_Catalog, DEFAULT.Initial_Catalog);
  238. _networkLibrary = ConvertValueToString(KEY.Network_Library, null);
  239. _password = ConvertValueToString(KEY.Password, DEFAULT.Password);
  240. _trustServerCertificate = ConvertValueToBoolean(KEY.TrustServerCertificate, DEFAULT.TrustServerCertificate);
  241. // Temporary string - this value is stored internally as an enum.
  242. string typeSystemVersionString = ConvertValueToString(KEY.Type_System_Version, null);
  243. string transactionBindingString = ConvertValueToString(KEY.TransactionBinding, null);
  244. _userID = ConvertValueToString(KEY.User_ID, DEFAULT.User_ID);
  245. _workstationId = ConvertValueToString(KEY.Workstation_Id, null);
  246. if (_contextConnection) {
  247. // We have to be running in the engine for you to request a
  248. // context connection.
  249. if (!runningInProc) {
  250. throw SQL.ContextUnavailableOutOfProc();
  251. }
  252. // When using a context connection, we need to ensure that no
  253. // other connection string keywords are specified.
  254. foreach (DictionaryEntry entry in Parsetable) {
  255. if ((string) entry.Key != KEY.Context_Connection &&
  256. (string) entry.Key != KEY.Type_System_Version) {
  257. throw SQL.ContextAllowsLimitedKeywords();
  258. }
  259. }
  260. }
  261. if (!_encrypt) { // Support legacy registry encryption settings
  262. const string folder = "Software\\Microsoft\\MSSQLServer\\Client\\SuperSocketNetLib";
  263. const string value = "Encrypt";
  264. Object obj = ADP.LocalMachineRegistryValue(folder, value);
  265. if ((obj is Int32) && (1 == (int)obj)) { // If the registry key exists
  266. _encrypt = true;
  267. }
  268. }
  269. if (_loadBalanceTimeout < 0) {
  270. throw ADP.InvalidConnectionOptionValue(KEY.Load_Balance_Timeout);
  271. }
  272. if (_connectTimeout < 0) {
  273. throw ADP.InvalidConnectionOptionValue(KEY.Connect_Timeout);
  274. }
  275. if (_maxPoolSize < 1) {
  276. throw ADP.InvalidConnectionOptionValue(KEY.Max_Pool_Size);
  277. }
  278. if (_minPoolSize < 0) {
  279. throw ADP.InvalidConnectionOptionValue(KEY.Min_Pool_Size);
  280. }
  281. if (_maxPoolSize < _minPoolSize) {
  282. throw ADP.InvalidMinMaxPoolSizeValues();
  283. }
  284. if ((_packetSize < TdsEnums.MIN_PACKET_SIZE) || (TdsEnums.MAX_PACKET_SIZE < _packetSize)) {
  285. throw SQL.InvalidPacketSizeValue();
  286. }
  287. if (null != _networkLibrary) { // MDAC 83525
  288. string networkLibrary = _networkLibrary.Trim().ToLower(CultureInfo.InvariantCulture);
  289. Hashtable netlib = NetlibMapping();
  290. if (!netlib.ContainsKey(networkLibrary)) {
  291. throw ADP.InvalidConnectionOptionValue(KEY.Network_Library);
  292. }
  293. _networkLibrary = (string) netlib[networkLibrary];
  294. }
  295. else {
  296. _networkLibrary = DEFAULT.Network_Library;
  297. }
  298. ValidateValueLength(_applicationName, TdsEnums.MAXLEN_APPNAME, KEY.Application_Name);
  299. ValidateValueLength(_currentLanguage , TdsEnums.MAXLEN_LANGUAGE, KEY.Current_Language);
  300. ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
  301. ValidateValueLength(_failoverPartner, TdsEnums.MAXLEN_SERVERNAME, KEY.FailoverPartner);
  302. ValidateValueLength(_initialCatalog, TdsEnums.MAXLEN_DATABASE, KEY.Initial_Catalog);
  303. ValidateValueLength(_password, TdsEnums.MAXLEN_PASSWORD, KEY.Password);
  304. ValidateValueLength(_userID, TdsEnums.MAXLEN_USERNAME, KEY.User_ID);
  305. if (null != _workstationId) {
  306. ValidateValueLength(_workstationId, TdsEnums.MAXLEN_HOSTNAME, KEY.Workstation_Id);
  307. }
  308. if (!String.Equals(DEFAULT.FailoverPartner, _failoverPartner, StringComparison.OrdinalIgnoreCase)) {
  309. // fail-over partner is set
  310. if (_multiSubnetFailover) {
  311. throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: false, internalConnection: null);
  312. }
  313. if (String.Equals(DEFAULT.Initial_Catalog, _initialCatalog, StringComparison.OrdinalIgnoreCase)) {
  314. throw ADP.MissingConnectionOptionValue(KEY.FailoverPartner, KEY.Initial_Catalog);
  315. }
  316. }
  317. // expand during construction so that CreatePermissionSet and Expand are consistent
  318. string datadir = null;
  319. _expandedAttachDBFilename = ExpandDataDirectory(KEY.AttachDBFilename, _attachDBFileName, ref datadir);
  320. if (null != _expandedAttachDBFilename) {
  321. if (0 <= _expandedAttachDBFilename.IndexOf('|')) {
  322. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  323. }
  324. ValidateValueLength(_expandedAttachDBFilename, TdsEnums.MAXLEN_ATTACHDBFILE, KEY.AttachDBFilename);
  325. if (_localDBInstance == null)
  326. {
  327. // fail fast to verify LocalHost when using |DataDirectory|
  328. // still must check again at connect time
  329. string host = _dataSource;
  330. string protocol = _networkLibrary;
  331. TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
  332. VerifyLocalHostAndFixup(ref host, true, false /*don't fix-up*/);
  333. }
  334. }
  335. else if (0 <= _attachDBFileName.IndexOf('|')) {
  336. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  337. }
  338. else {
  339. ValidateValueLength(_attachDBFileName, TdsEnums.MAXLEN_ATTACHDBFILE, KEY.AttachDBFilename);
  340. }
  341. _typeSystemAssemblyVersion = constTypeSystemAsmVersion10;
  342. if (true == _userInstance && !ADP.IsEmpty(_failoverPartner)) {
  343. throw SQL.UserInstanceFailoverNotCompatible();
  344. }
  345. if (ADP.IsEmpty(typeSystemVersionString)) {
  346. typeSystemVersionString = DbConnectionStringDefaults.TypeSystemVersion;
  347. }
  348. if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.Latest, StringComparison.OrdinalIgnoreCase)) {
  349. _typeSystemVersion = TypeSystem.Latest;
  350. }
  351. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2000, StringComparison.OrdinalIgnoreCase)) {
  352. if (_contextConnection) {
  353. throw SQL.ContextAllowsOnlyTypeSystem2005();
  354. }
  355. _typeSystemVersion = TypeSystem.SQLServer2000;
  356. }
  357. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2005, StringComparison.OrdinalIgnoreCase)) {
  358. _typeSystemVersion = TypeSystem.SQLServer2005;
  359. }
  360. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2008, StringComparison.OrdinalIgnoreCase)) {
  361. _typeSystemVersion = TypeSystem.SQLServer2008;
  362. }
  363. else if (typeSystemVersionString.Equals(TYPESYSTEMVERSION.SQL_Server_2012, StringComparison.OrdinalIgnoreCase)) {
  364. _typeSystemVersion = TypeSystem.SQLServer2012;
  365. _typeSystemAssemblyVersion = constTypeSystemAsmVersion11;
  366. }
  367. else {
  368. throw ADP.InvalidConnectionOptionValue(KEY.Type_System_Version);
  369. }
  370. if (ADP.IsEmpty(transactionBindingString)) {
  371. transactionBindingString = DbConnectionStringDefaults.TransactionBinding;
  372. }
  373. if (transactionBindingString.Equals(TRANSACIONBINDING.ImplicitUnbind, StringComparison.OrdinalIgnoreCase)) {
  374. _transactionBinding = TransactionBindingEnum.ImplicitUnbind;
  375. }
  376. else if (transactionBindingString.Equals(TRANSACIONBINDING.ExplicitUnbind, StringComparison.OrdinalIgnoreCase)) {
  377. _transactionBinding = TransactionBindingEnum.ExplicitUnbind;
  378. }
  379. else {
  380. throw ADP.InvalidConnectionOptionValue(KEY.TransactionBinding);
  381. }
  382. if (_applicationIntent == ApplicationIntent.ReadOnly && !String.IsNullOrEmpty(_failoverPartner))
  383. throw SQL.ROR_FailoverNotSupportedConnString();
  384. if ((_connectRetryCount<0) || (_connectRetryCount>255)) {
  385. throw ADP.InvalidConnectRetryCountValue();
  386. }
  387. if ((_connectRetryInterval < 1) || (_connectRetryInterval > 60)) {
  388. throw ADP.InvalidConnectRetryIntervalValue();
  389. }
  390. }
  391. // This c-tor is used to create SSE and user instance connection strings when user instance is set to true
  392. //
  393. internal SqlConnectionString(SqlConnectionString connectionOptions, string dataSource, bool userInstance, bool? setEnlistValue) : base(connectionOptions) {
  394. _integratedSecurity = connectionOptions._integratedSecurity;
  395. _connectionReset = connectionOptions._connectionReset;
  396. _contextConnection = connectionOptions._contextConnection;
  397. _encrypt = connectionOptions._encrypt;
  398. if (setEnlistValue.HasValue) {
  399. _enlist = setEnlistValue.Value;
  400. }
  401. else {
  402. _enlist = connectionOptions._enlist;
  403. }
  404. _mars = connectionOptions._mars;
  405. _persistSecurityInfo = connectionOptions._persistSecurityInfo;
  406. _pooling = connectionOptions._pooling;
  407. _replication = connectionOptions._replication;
  408. _userInstance = userInstance;
  409. _connectTimeout = connectionOptions._connectTimeout;
  410. _loadBalanceTimeout = connectionOptions._loadBalanceTimeout;
  411. _maxPoolSize = connectionOptions._maxPoolSize;
  412. _minPoolSize = connectionOptions._minPoolSize;
  413. _multiSubnetFailover = connectionOptions._multiSubnetFailover;
  414. _packetSize = connectionOptions._packetSize;
  415. _applicationName = connectionOptions._applicationName;
  416. _attachDBFileName = connectionOptions._attachDBFileName;
  417. _currentLanguage = connectionOptions._currentLanguage;
  418. _dataSource = dataSource;
  419. _localDBInstance = LocalDBAPI.GetLocalDbInstanceNameFromServerName(_dataSource);
  420. _failoverPartner = connectionOptions._failoverPartner;
  421. _initialCatalog = connectionOptions._initialCatalog;
  422. _password = connectionOptions._password;
  423. _userID = connectionOptions._userID;
  424. _networkLibrary = connectionOptions._networkLibrary;
  425. _workstationId = connectionOptions._workstationId;
  426. _expandedAttachDBFilename = connectionOptions._expandedAttachDBFilename;
  427. _typeSystemVersion = connectionOptions._typeSystemVersion;
  428. _typeSystemAssemblyVersion =connectionOptions._typeSystemAssemblyVersion;
  429. _transactionBinding = connectionOptions._transactionBinding;
  430. _applicationIntent = connectionOptions._applicationIntent;
  431. _connectRetryCount = connectionOptions._connectRetryCount;
  432. _connectRetryInterval = connectionOptions._connectRetryInterval;
  433. ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
  434. }
  435. internal bool IntegratedSecurity { get { return _integratedSecurity; } }
  436. // We always initialize in Async mode so that both synchronous and asynchronous methods
  437. // will work. In the future we can deprecate the keyword entirely.
  438. internal bool Asynchronous { get { return true; } }
  439. // SQLPT 41700: Ignore ResetConnection=False, always reset the connection for security
  440. internal bool ConnectionReset { get { return true; } }
  441. internal bool ContextConnection { get { return _contextConnection; } }
  442. // internal bool EnableUdtDownload { get { return _enableUdtDownload;} }
  443. internal bool Encrypt { get { return _encrypt; } }
  444. internal bool TrustServerCertificate { get { return _trustServerCertificate; } }
  445. internal bool Enlist { get { return _enlist; } }
  446. internal bool MARS { get { return _mars; } }
  447. internal bool MultiSubnetFailover { get { return _multiSubnetFailover; } }
  448. internal bool PersistSecurityInfo { get { return _persistSecurityInfo; } }
  449. internal bool Pooling { get { return _pooling; } }
  450. internal bool Replication { get { return _replication; } }
  451. internal bool UserInstance { get { return _userInstance; } }
  452. internal int ConnectTimeout { get { return _connectTimeout; } }
  453. internal int LoadBalanceTimeout { get { return _loadBalanceTimeout; } }
  454. internal int MaxPoolSize { get { return _maxPoolSize; } }
  455. internal int MinPoolSize { get { return _minPoolSize; } }
  456. internal int PacketSize { get { return _packetSize; } }
  457. internal int ConnectRetryCount { get { return _connectRetryCount; } }
  458. internal int ConnectRetryInterval { get { return _connectRetryInterval; } }
  459. internal ApplicationIntent ApplicationIntent { get { return _applicationIntent; } }
  460. internal string ApplicationName { get { return _applicationName; } }
  461. internal string AttachDBFilename { get { return _attachDBFileName; } }
  462. internal string CurrentLanguage { get { return _currentLanguage; } }
  463. internal string DataSource { get { return _dataSource; } }
  464. internal string LocalDBInstance { get { return _localDBInstance; } }
  465. internal string FailoverPartner { get { return _failoverPartner; } }
  466. internal string InitialCatalog { get { return _initialCatalog; } }
  467. internal string NetworkLibrary { get { return _networkLibrary; } }
  468. internal string Password { get { return _password; } }
  469. internal string UserID { get { return _userID; } }
  470. internal string WorkstationId { get { return _workstationId; } }
  471. internal TypeSystem TypeSystemVersion { get { return _typeSystemVersion; } }
  472. internal Version TypeSystemAssemblyVersion { get { return _typeSystemAssemblyVersion; } }
  473. internal TransactionBindingEnum TransactionBinding { get { return _transactionBinding; } }
  474. internal bool EnforceLocalHost {
  475. get {
  476. // so tdsparser.connect can determine if SqlConnection.UserConnectionOptions
  477. // needs to enfoce local host after datasource alias lookup
  478. return (null != _expandedAttachDBFilename) && (null == _localDBInstance);
  479. }
  480. }
  481. protected internal override System.Security.PermissionSet CreatePermissionSet() {
  482. System.Security.PermissionSet permissionSet = new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None);
  483. permissionSet.AddPermission(new SqlClientPermission(this));
  484. return permissionSet;
  485. }
  486. protected internal override string Expand() {
  487. if (null != _expandedAttachDBFilename) {
  488. return ExpandKeyword(KEY.AttachDBFilename, _expandedAttachDBFilename);
  489. }
  490. else {
  491. return base.Expand();
  492. }
  493. }
  494. private static bool CompareHostName(ref string host, string name, bool fixup) {
  495. // same computer name or same computer name + "\named instance"
  496. bool equal = false;
  497. if (host.Equals(name, StringComparison.OrdinalIgnoreCase)) {
  498. if (fixup) {
  499. host = ".";
  500. }
  501. equal = true;
  502. }
  503. else if (host.StartsWith(name+@"\", StringComparison.OrdinalIgnoreCase)) {
  504. if (fixup) {
  505. host = "." + host.Substring(name.Length);
  506. }
  507. equal = true;
  508. }
  509. return equal;
  510. }
  511. // this hashtable is meant to be read-only translation of parsed string
  512. // keywords/synonyms to a known keyword string
  513. internal static Hashtable GetParseSynonyms() {
  514. Hashtable hash = _sqlClientSynonyms;
  515. if (null == hash) {
  516. hash = new Hashtable(SqlConnectionStringBuilder.KeywordsCount + SynonymCount);
  517. hash.Add(KEY.ApplicationIntent, KEY.ApplicationIntent);
  518. hash.Add(KEY.Application_Name, KEY.Application_Name);
  519. hash.Add(KEY.AsynchronousProcessing, KEY.AsynchronousProcessing);
  520. hash.Add(KEY.AttachDBFilename, KEY.AttachDBFilename);
  521. hash.Add(KEY.Connect_Timeout, KEY.Connect_Timeout);
  522. hash.Add(KEY.Connection_Reset, KEY.Connection_Reset);
  523. hash.Add(KEY.Context_Connection, KEY.Context_Connection);
  524. hash.Add(KEY.Current_Language, KEY.Current_Language);
  525. hash.Add(KEY.Data_Source, KEY.Data_Source);
  526. hash.Add(KEY.Encrypt, KEY.Encrypt);
  527. hash.Add(KEY.Enlist, KEY.Enlist);
  528. hash.Add(KEY.FailoverPartner, KEY.FailoverPartner);
  529. hash.Add(KEY.Initial_Catalog, KEY.Initial_Catalog);
  530. hash.Add(KEY.Integrated_Security, KEY.Integrated_Security);
  531. hash.Add(KEY.Load_Balance_Timeout, KEY.Load_Balance_Timeout);
  532. hash.Add(KEY.MARS, KEY.MARS);
  533. hash.Add(KEY.Max_Pool_Size, KEY.Max_Pool_Size);
  534. hash.Add(KEY.Min_Pool_Size, KEY.Min_Pool_Size);
  535. hash.Add(KEY.MultiSubnetFailover, KEY.MultiSubnetFailover);
  536. hash.Add(KEY.Network_Library, KEY.Network_Library);
  537. hash.Add(KEY.Packet_Size, KEY.Packet_Size);
  538. hash.Add(KEY.Password, KEY.Password);
  539. hash.Add(KEY.Persist_Security_Info, KEY.Persist_Security_Info);
  540. hash.Add(KEY.Pooling, KEY.Pooling);
  541. hash.Add(KEY.Replication, KEY.Replication);
  542. hash.Add(KEY.TrustServerCertificate, KEY.TrustServerCertificate);
  543. hash.Add(KEY.TransactionBinding, KEY.TransactionBinding);
  544. hash.Add(KEY.Type_System_Version, KEY.Type_System_Version);
  545. hash.Add(KEY.User_ID, KEY.User_ID);
  546. hash.Add(KEY.User_Instance, KEY.User_Instance);
  547. hash.Add(KEY.Workstation_Id, KEY.Workstation_Id);
  548. hash.Add(KEY.Connect_Retry_Count, KEY.Connect_Retry_Count);
  549. hash.Add(KEY.Connect_Retry_Interval, KEY.Connect_Retry_Interval);
  550. hash.Add(SYNONYM.APP, KEY.Application_Name);
  551. hash.Add(SYNONYM.Async, KEY.AsynchronousProcessing);
  552. hash.Add(SYNONYM.EXTENDED_PROPERTIES, KEY.AttachDBFilename);
  553. hash.Add(SYNONYM.INITIAL_FILE_NAME, KEY.AttachDBFilename);
  554. hash.Add(SYNONYM.CONNECTION_TIMEOUT, KEY.Connect_Timeout);
  555. hash.Add(SYNONYM.TIMEOUT, KEY.Connect_Timeout);
  556. hash.Add(SYNONYM.LANGUAGE, KEY.Current_Language);
  557. hash.Add(SYNONYM.ADDR, KEY.Data_Source);
  558. hash.Add(SYNONYM.ADDRESS, KEY.Data_Source);
  559. hash.Add(SYNONYM.NETWORK_ADDRESS, KEY.Data_Source);
  560. hash.Add(SYNONYM.SERVER, KEY.Data_Source);
  561. hash.Add(SYNONYM.DATABASE, KEY.Initial_Catalog);
  562. hash.Add(SYNONYM.TRUSTED_CONNECTION, KEY.Integrated_Security);
  563. hash.Add(SYNONYM.Connection_Lifetime, KEY.Load_Balance_Timeout);
  564. hash.Add(SYNONYM.NET, KEY.Network_Library);
  565. hash.Add(SYNONYM.NETWORK, KEY.Network_Library);
  566. hash.Add(SYNONYM.Pwd, KEY.Password);
  567. hash.Add(SYNONYM.PERSISTSECURITYINFO, KEY.Persist_Security_Info);
  568. hash.Add(SYNONYM.UID, KEY.User_ID);
  569. hash.Add(SYNONYM.User, KEY.User_ID);
  570. hash.Add(SYNONYM.WSID, KEY.Workstation_Id);
  571. Debug.Assert(SqlConnectionStringBuilder.KeywordsCount + SynonymCount == hash.Count, "incorrect initial ParseSynonyms size");
  572. _sqlClientSynonyms = hash;
  573. }
  574. return hash;
  575. }
  576. internal string ObtainWorkstationId() {
  577. // If not supplied by the user, the default value is the MachineName
  578. // Note: In Longhorn you'll be able to rename a machine without
  579. // rebooting. Therefore, don't cache this machine name.
  580. string result = WorkstationId;
  581. if (null == result) {
  582. // permission to obtain Environment.MachineName is Asserted
  583. // since permission to open the connection has been granted
  584. // the information is shared with the server, but not directly with the user
  585. result = ADP.MachineName();
  586. ValidateValueLength(result, TdsEnums.MAXLEN_HOSTNAME, KEY.Workstation_Id);
  587. }
  588. return result;
  589. }
  590. static internal Hashtable NetlibMapping() {
  591. const int NetLibCount = 8;
  592. Hashtable hash = _netlibMapping;
  593. if (null == hash) {
  594. hash = new Hashtable(NetLibCount);
  595. hash.Add(NETLIB.TCPIP, TdsEnums.TCP);
  596. hash.Add(NETLIB.NamedPipes, TdsEnums.NP);
  597. hash.Add(NETLIB.Multiprotocol, TdsEnums.RPC);
  598. hash.Add(NETLIB.BanyanVines, TdsEnums.BV);
  599. hash.Add(NETLIB.AppleTalk, TdsEnums.ADSP);
  600. hash.Add(NETLIB.IPXSPX, TdsEnums.SPX);
  601. hash.Add(NETLIB.VIA, TdsEnums.VIA);
  602. hash.Add(NETLIB.SharedMemory, TdsEnums.LPC);
  603. Debug.Assert(NetLibCount == hash.Count, "incorrect initial NetlibMapping size");
  604. _netlibMapping = hash;
  605. }
  606. return hash;
  607. }
  608. static internal bool ValidProtocal (string protocal) {
  609. switch (protocal) {
  610. case TdsEnums.TCP :
  611. case TdsEnums.NP :
  612. case TdsEnums.VIA :
  613. case TdsEnums.LPC :
  614. return true;
  615. // case TdsEnums.RPC : Invalid Protocals
  616. // case TdsEnums.BV :
  617. // case TdsEnums.ADSP :
  618. // case TdsEnums.SPX :
  619. default :
  620. return false;
  621. }
  622. }
  623. private void ValidateValueLength (string value, int limit, string key) {
  624. if (limit < value.Length) {
  625. throw ADP.InvalidConnectionOptionValueLength(key, limit);
  626. }
  627. }
  628. internal static void VerifyLocalHostAndFixup(ref string host, bool enforceLocalHost, bool fixup) {
  629. if (ADP.IsEmpty(host)) {
  630. if (fixup) {
  631. host = ".";
  632. }
  633. }
  634. else if (!CompareHostName(ref host, @".", fixup) &&
  635. !CompareHostName(ref host, @"(local)", fixup)) {
  636. // Fix-up completed in CompareHostName if return value true.
  637. string name = ADP.GetComputerNameDnsFullyQualified(); // i.e, machine.location.corp.company.com
  638. if (!CompareHostName(ref host, name, fixup)) {
  639. int separatorPos = name.IndexOf('.'); // to compare just 'machine' part
  640. if ((separatorPos <= 0) || !CompareHostName(ref host, name.Substring(0, separatorPos), fixup)) {
  641. if (enforceLocalHost) {
  642. throw ADP.InvalidConnectionOptionValue(KEY.AttachDBFilename);
  643. }
  644. }
  645. }
  646. }
  647. }
  648. internal System.Data.SqlClient.ApplicationIntent ConvertValueToApplicationIntent() {
  649. object value = base.Parsetable[KEY.ApplicationIntent];
  650. if (value == null) {
  651. return DEFAULT.ApplicationIntent;
  652. }
  653. // when wrong value is used in the connection string provided to SqlConnection.ConnectionString or c-tor,
  654. // wrap Format and Overflow exceptions with Argument one, to be consistent with rest of the keyword types (like int and bool)
  655. try {
  656. return DbConnectionStringBuilderUtil.ConvertToApplicationIntent(KEY.ApplicationIntent, value);
  657. }
  658. catch (FormatException e) {
  659. throw ADP.InvalidConnectionOptionValue(KEY.ApplicationIntent, e);
  660. }
  661. catch (OverflowException e) {
  662. throw ADP.InvalidConnectionOptionValue(KEY.ApplicationIntent, e);
  663. }
  664. // ArgumentException and other types are raised as is (no wrapping)
  665. }
  666. }
  667. }