You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			1146 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1146 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // <copyright file="TdsParserHelperClasses.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.SqlClient {
 | |
|     using System;
 | |
|     using System.Collections.Generic;
 | |
|     using System.Data;
 | |
|     using System.Data.Common;
 | |
|     using System.Data.ProviderBase;
 | |
|     using System.Data.Sql;
 | |
|     using System.Data.SqlTypes;
 | |
|     using System.Diagnostics;
 | |
|     using System.Reflection;
 | |
|     using System.Text;
 | |
|     using System.Threading;
 | |
|     using System.Security;
 | |
|     using System.Globalization;
 | |
| 
 | |
|     using Microsoft.SqlServer.Server; // for SMI metadata
 | |
| 
 | |
|     internal enum CallbackType {
 | |
|         Read  = 0,
 | |
|         Write = 1
 | |
|     }
 | |
| 
 | |
|     internal enum EncryptionOptions {
 | |
|         OFF,
 | |
|         ON,
 | |
|         NOT_SUP,
 | |
|         REQ,
 | |
|         LOGIN
 | |
|     }
 | |
| 
 | |
|     internal enum PreLoginHandshakeStatus {
 | |
|         Successful,
 | |
|         InstanceFailure
 | |
|     }
 | |
| 
 | |
|     internal enum PreLoginOptions {
 | |
|         VERSION,
 | |
|         ENCRYPT,
 | |
|         INSTANCE,
 | |
|         THREADID,
 | |
|         MARS,
 | |
|         TRACEID,
 | |
|         FEDAUTHREQUIRED,
 | |
|         NUMOPT,
 | |
|         LASTOPT = 255
 | |
|     }
 | |
| 
 | |
|     internal enum RunBehavior {
 | |
|         UntilDone         =  1, // 0001 binary
 | |
|         ReturnImmediately =  2, // 0010 binary
 | |
|         Clean             =  5, // 0101 binary - Clean AND UntilDone
 | |
|         Attention         = 13  // 1101 binary - Clean AND UntilDone AND Attention
 | |
|     }
 | |
| 
 | |
|     internal enum TdsParserState {
 | |
|         Closed,
 | |
|         OpenNotLoggedIn,
 | |
|         OpenLoggedIn,
 | |
|         Broken,
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Struct encapsulating the data to be sent to the server as part of Federated Authentication Feature Extension.
 | |
|     /// </summary>
 | |
|     internal struct FederatedAuthenticationFeatureExtensionData
 | |
|     {
 | |
|         internal TdsEnums.FedAuthLibrary libraryType;
 | |
|         internal bool fedAuthRequiredPreLoginResponse;
 | |
|         internal SqlAuthenticationMethod authentication;
 | |
|         internal byte[] accessToken;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// <para> Represents a single encrypted value for a CEK. It contains the encrypted CEK,
 | |
|     ///  the store type, name,the key path and encryption algorithm.</para>
 | |
|     /// </summary>
 | |
|     internal struct SqlEncryptionKeyInfo {
 | |
|         internal byte[] encryptedKey; // the encrypted "column encryption key"
 | |
|         internal int databaseId;
 | |
|         internal int cekId;
 | |
|         internal int cekVersion;
 | |
|         internal byte[] cekMdVersion;
 | |
|         internal string keyPath;
 | |
|         internal string keyStoreName;
 | |
|         internal string algorithmName;
 | |
|         internal byte normalizationRuleVersion;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// <para> Encapsulates one entry in the CipherInfo table sent as part of Colmetadata.
 | |
|     /// The same CEK is encrypted multiple times with different master keys (for master key
 | |
|     /// rotation scenario) We need to keep all these around until we can resolve the CEK
 | |
|     /// using the correct master key.</para>
 | |
|     /// </summary>
 | |
|     internal struct SqlTceCipherInfoEntry {
 | |
| 
 | |
|         /// <summary>
 | |
|         /// List of Column Encryption Key Information.
 | |
|         /// </summary>
 | |
|         private readonly List<SqlEncryptionKeyInfo> _columnEncryptionKeyValues;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Key Ordinal.
 | |
|         /// </summary>
 | |
|         private readonly int _ordinal;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Database ID
 | |
|         /// </summary>
 | |
|         private int _databaseId;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Cek ID
 | |
|         /// </summary>
 | |
|         private int _cekId;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Cek Version
 | |
|         /// </summary>
 | |
|         private int _cekVersion;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Cek MD Version
 | |
|         /// </summary>
 | |
|         private byte[] _cekMdVersion;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the ordinal.
 | |
|         /// </summary>
 | |
|         internal int Ordinal {
 | |
|             get {
 | |
|                 return _ordinal;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the DatabaseID.
 | |
|         /// </summary>
 | |
|         internal int DatabaseId {
 | |
|             get {
 | |
|                 return _databaseId;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the CEK ID.
 | |
|         /// </summary>
 | |
|         internal int CekId {
 | |
|             get {
 | |
|                 return _cekId;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the CEK Version.
 | |
|         /// </summary>
 | |
|         internal int CekVersion {
 | |
|             get {
 | |
|                 return _cekVersion;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the CEK MD Version.
 | |
|         /// </summary>
 | |
|         internal byte[] CekMdVersion {
 | |
|             get {
 | |
|                 return _cekMdVersion;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the list of Column Encryption Key Values.
 | |
|         /// </summary>
 | |
|         internal List<SqlEncryptionKeyInfo> ColumnEncryptionKeyValues {
 | |
|             get {
 | |
|                 return _columnEncryptionKeyValues;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Add an entry to the list of ColumnEncryptionKeyValues.
 | |
|         /// </summary>
 | |
|         /// <param name="encryptedKey"></param>
 | |
|         /// <param name="databaseId"></param>
 | |
|         /// <param name="cekId"></param>
 | |
|         /// <param name="cekVersion"></param>
 | |
|         /// <param name="cekMdVersion"></param>
 | |
|         /// <param name="keyPath"></param>
 | |
|         /// <param name="keyStoreName"></param>
 | |
|         /// <param name="algorithmName"></param>
 | |
|         internal void Add(byte[] encryptedKey, int databaseId, int cekId, int cekVersion, byte[] cekMdVersion, string keyPath, string keyStoreName, string algorithmName) {
 | |
| 
 | |
|             Debug.Assert(_columnEncryptionKeyValues != null, "_columnEncryptionKeyValues should already be initialized.");
 | |
| 
 | |
|             SqlEncryptionKeyInfo encryptionKey = new SqlEncryptionKeyInfo();
 | |
|             encryptionKey.encryptedKey = encryptedKey;
 | |
|             encryptionKey.databaseId = databaseId;
 | |
|             encryptionKey.cekId = cekId;
 | |
|             encryptionKey.cekVersion = cekVersion;
 | |
|             encryptionKey.cekMdVersion = cekMdVersion;
 | |
|             encryptionKey.keyPath = keyPath;
 | |
|             encryptionKey.keyStoreName = keyStoreName;
 | |
|             encryptionKey.algorithmName = algorithmName;
 | |
|             _columnEncryptionKeyValues.Add(encryptionKey);
 | |
| 
 | |
|             if (0 == _databaseId) {
 | |
|                 _databaseId = databaseId;
 | |
|                 _cekId = cekId;
 | |
|                 _cekVersion = cekVersion;
 | |
|                 _cekMdVersion = cekMdVersion;
 | |
|             }
 | |
|             else {
 | |
|                 Debug.Assert(_databaseId == databaseId);
 | |
|                 Debug.Assert(_cekId == cekId);
 | |
|                 Debug.Assert(_cekVersion == cekVersion);
 | |
|                 Debug.Assert (_cekMdVersion != null && cekMdVersion != null && _cekMdVersion.Length == _cekMdVersion.Length);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Constructor.
 | |
|         /// </summary>
 | |
|         /// <param name="ordinal"></param>
 | |
|         internal SqlTceCipherInfoEntry(int ordinal = 0) : this() {
 | |
|             _ordinal = ordinal;
 | |
|             _databaseId = 0;
 | |
|             _cekId = 0;
 | |
|             _cekVersion = 0;
 | |
|             _cekMdVersion = null;
 | |
|             _columnEncryptionKeyValues = new List<SqlEncryptionKeyInfo>();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary> 
 | |
|     /// <para> Represents a table with various CEKs used in a resultset. Each entry corresponds to one (unique) CEK. The CEK
 | |
|     /// may have been encrypted using multiple master keys (giving us multiple CEK values). All these values form one single
 | |
|     /// entry in this table.</para>
 | |
|     ///</summary>
 | |
|     internal struct SqlTceCipherInfoTable {
 | |
|         private readonly SqlTceCipherInfoEntry [] keyList;
 | |
| 
 | |
|         internal SqlTceCipherInfoTable (int tabSize) {
 | |
|             Debug.Assert (0 < tabSize, "Invalid Table Size");
 | |
|             keyList = new SqlTceCipherInfoEntry[tabSize];
 | |
|         }
 | |
| 
 | |
|         internal SqlTceCipherInfoEntry this [int index] {
 | |
|             get {
 | |
|                 Debug.Assert (index < keyList.Length, "Invalid index specified.");
 | |
|                 return keyList[index];
 | |
|             }
 | |
|             set {
 | |
|                 Debug.Assert (index < keyList.Length, "Invalid index specified.");
 | |
|                 keyList[index] = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal int Size {
 | |
|             get {
 | |
|                 return keyList.Length;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlCollation {
 | |
|         // First 20 bits of info field represent the lcid, bits 21-25 are compare options
 | |
|         private const uint IgnoreCase     = 1 << 20; // bit 21 - IgnoreCase
 | |
|         private const uint IgnoreNonSpace = 1 << 21; // bit 22 - IgnoreNonSpace / IgnoreAccent
 | |
|         private const uint IgnoreWidth    = 1 << 22; // bit 23 - IgnoreWidth
 | |
|         private const uint IgnoreKanaType = 1 << 23; // bit 24 - IgnoreKanaType
 | |
|         private const uint BinarySort     = 1 << 24; // bit 25 - BinarySort
 | |
| 
 | |
|         internal const uint MaskLcid           = 0xfffff;
 | |
|         private const int LcidVersionBitOffset = 28;
 | |
|         private const uint MaskLcidVersion     = unchecked((uint)(0xf << LcidVersionBitOffset));
 | |
|         private const uint MaskCompareOpt = IgnoreCase | IgnoreNonSpace | IgnoreWidth | IgnoreKanaType | BinarySort;
 | |
| 
 | |
|         internal uint info;
 | |
|         internal byte sortId;
 | |
| 
 | |
|         static int FirstSupportedCollationVersion(int lcid)
 | |
|         {
 | |
|             // NOTE: switch-case works ~3 times faster in this case than search with Dictionary
 | |
|             switch (lcid)
 | |
|             {
 | |
|                 case 1044: return 2; // Norwegian_100_BIN
 | |
|                 case 1047: return 2; // Romansh_100_BIN
 | |
|                 case 1056: return 2; // Urdu_100_BIN
 | |
|                 case 1065: return 2; // Persian_100_BIN
 | |
|                 case 1068: return 2; // Azeri_Latin_100_BIN
 | |
|                 case 1070: return 2; // Upper_Sorbian_100_BIN
 | |
|                 case 1071: return 1; // ----n_FYROM_90_BIN
 | |
|                 case 1081: return 1; // Indic_General_90_BIN
 | |
|                 case 1082: return 2; // Maltese_100_BIN
 | |
|                 case 1083: return 2; // Sami_Norway_100_BIN
 | |
|                 case 1087: return 1; // Kazakh_90_BIN
 | |
|                 case 1090: return 2; // Turkmen_100_BIN
 | |
|                 case 1091: return 1; // Uzbek_Latin_90_BIN
 | |
|                 case 1092: return 1; // Tatar_90_BIN
 | |
|                 case 1093: return 2; // Bengali_100_BIN
 | |
|                 case 1101: return 2; // Assamese_100_BIN
 | |
|                 case 1105: return 2; // Tibetan_100_BIN
 | |
|                 case 1106: return 2; // Welsh_100_BIN
 | |
|                 case 1107: return 2; // Khmer_100_BIN
 | |
|                 case 1108: return 2; // Lao_100_BIN
 | |
|                 case 1114: return 1; // Syriac_90_BIN
 | |
|                 case 1121: return 2; // Nepali_100_BIN
 | |
|                 case 1122: return 2; // Frisian_100_BIN
 | |
|                 case 1123: return 2; // Pashto_100_BIN
 | |
|                 case 1125: return 1; // Divehi_90_BIN
 | |
|                 case 1133: return 2; // Bashkir_100_BIN
 | |
|                 case 1146: return 2; // Mapudungan_100_BIN
 | |
|                 case 1148: return 2; // Mohawk_100_BIN
 | |
|                 case 1150: return 2; // Breton_100_BIN
 | |
|                 case 1152: return 2; // Uighur_100_BIN
 | |
|                 case 1153: return 2; // Maori_100_BIN
 | |
|                 case 1155: return 2; // Corsican_100_BIN
 | |
|                 case 1157: return 2; // Yakut_100_BIN
 | |
|                 case 1164: return 2; // Dari_100_BIN
 | |
|                 case 2074: return 2; // Serbian_Latin_100_BIN
 | |
|                 case 2092: return 2; // Azeri_Cyrillic_100_BIN
 | |
|                 case 2107: return 2; // Sami_Sweden_Finland_100_BIN
 | |
|                 case 2143: return 2; // Tamazight_100_BIN
 | |
|                 case 3076: return 1; // Chinese_Hong_Kong_Stroke_90_BIN
 | |
|                 case 3098: return 2; // Serbian_Cyrillic_100_BIN
 | |
|                 case 5124: return 2; // Chinese_Traditional_Pinyin_100_BIN
 | |
|                 case 5146: return 2; // Bosnian_Latin_100_BIN
 | |
|                 case 8218: return 2; // Bosnian_Cyrillic_100_BIN
 | |
| 
 | |
|                 default: return 0;   // other LCIDs have collation with version 0
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal int LCID {
 | |
|             // First 20 bits of info field represent the lcid
 | |
|             get {
 | |
|                 return unchecked((int)(info & MaskLcid));
 | |
|             }
 | |
|             set {
 | |
|                 int lcid = value & (int)MaskLcid;
 | |
|                 Debug.Assert(lcid == value, "invalid set_LCID value");
 | |
| 
 | |
|                 // VSTFDEVDIV 479474: some new Katmai LCIDs do not have collation with version = 0
 | |
|                 // since user has no way to specify collation version, we set the first (minimal) supported version for these collations
 | |
|                 int versionBits = FirstSupportedCollationVersion(lcid) << LcidVersionBitOffset;
 | |
|                 Debug.Assert((versionBits & MaskLcidVersion) == versionBits, "invalid version returned by FirstSupportedCollationVersion");
 | |
| 
 | |
|                 // combine the current compare options with the new locale ID and its first supported version
 | |
|                 info = (info & MaskCompareOpt) | unchecked((uint)lcid) | unchecked((uint)versionBits);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal SqlCompareOptions SqlCompareOptions {
 | |
|             get {
 | |
|                 SqlCompareOptions options = SqlCompareOptions.None;
 | |
|                 if (0 != (info & IgnoreCase))
 | |
|                     options |= SqlCompareOptions.IgnoreCase;
 | |
|                 if (0 != (info & IgnoreNonSpace))
 | |
|                     options |= SqlCompareOptions.IgnoreNonSpace;
 | |
|                 if (0 != (info & IgnoreWidth))
 | |
|                     options |= SqlCompareOptions.IgnoreWidth;
 | |
|                 if (0 != (info & IgnoreKanaType))
 | |
|                     options |= SqlCompareOptions.IgnoreKanaType;
 | |
|                 if (0 != (info & BinarySort))
 | |
|                     options |= SqlCompareOptions.BinarySort;
 | |
|                 return options;
 | |
|             }
 | |
|             set {
 | |
|                 Debug.Assert((value & SqlString.x_iValidSqlCompareOptionMask) == value, "invalid set_SqlCompareOptions value");
 | |
|                 uint tmp = 0;
 | |
|                 if (0 != (value & SqlCompareOptions.IgnoreCase))
 | |
|                     tmp |= IgnoreCase;
 | |
|                 if (0 != (value & SqlCompareOptions.IgnoreNonSpace))
 | |
|                     tmp |= IgnoreNonSpace;
 | |
|                 if (0 != (value & SqlCompareOptions.IgnoreWidth))
 | |
|                     tmp |= IgnoreWidth;
 | |
|                 if (0 != (value & SqlCompareOptions.IgnoreKanaType))
 | |
|                     tmp |= IgnoreKanaType;
 | |
|                 if (0 != (value & SqlCompareOptions.BinarySort))
 | |
|                     tmp |= BinarySort;
 | |
|                 info = (info & MaskLcid) | tmp;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal string TraceString() {
 | |
|             return String.Format(/*IFormatProvider*/ null, "(LCID={0}, Opts={1})", this.LCID, (int)this.SqlCompareOptions);
 | |
|         }
 | |
| 
 | |
|         static internal bool AreSame(SqlCollation a, SqlCollation b) {
 | |
|             if (a == null || b == null) {
 | |
|                 return a == b;
 | |
|             }
 | |
|             else {
 | |
|                 return a.info == b.info && a.sortId == b.sortId;
 | |
|             }
 | |
| 
 | |
|         }
 | |
|       
 | |
|     }
 | |
| 
 | |
|     internal class RoutingInfo {
 | |
|         internal byte Protocol { get; private set; }
 | |
|         internal UInt16 Port { get; private set; }
 | |
|         internal string ServerName { get; private set; }
 | |
| 
 | |
|         internal RoutingInfo(byte protocol, UInt16 port, string servername) {
 | |
|             Protocol = protocol;
 | |
|             Port = port;
 | |
|             ServerName = servername;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlEnvChange {
 | |
|         internal byte         type;
 | |
|         internal byte         oldLength;
 | |
|         internal int          newLength; // 7206 TDS changes makes this length an int
 | |
|         internal int          length;
 | |
|         internal string       newValue;
 | |
|         internal string       oldValue;
 | |
|         internal byte[]       newBinValue;
 | |
|         internal byte[]       oldBinValue;
 | |
|         internal long         newLongValue;
 | |
|         internal long         oldLongValue;
 | |
|         internal SqlCollation newCollation;
 | |
|         internal SqlCollation oldCollation;
 | |
|         internal RoutingInfo  newRoutingInfo;
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlLogin {
 | |
|         internal SqlAuthenticationMethod authentication = SqlAuthenticationMethod.NotSpecified;               // Authentication type
 | |
|         internal int timeout;                                                       // login timeout
 | |
|         internal bool   userInstance     = false;                                   // user instance
 | |
|         internal string hostName         = "";                                      // client machine name
 | |
|         internal string userName         = "";                                      // user id
 | |
|         internal string password         = "";                                      // password
 | |
|         internal string applicationName  = "";                                      // application name
 | |
|         internal string serverName       = "";                                      // server name
 | |
|         internal string language         = "";                                      // initial language
 | |
|         internal string database         = "";                                      // initial database
 | |
|         internal string attachDBFilename = "";                                      // DB filename to be attached
 | |
|         internal string newPassword      = "";                                      // new password for reset password
 | |
|         internal bool   useReplication   = false;                                   // user login for replication
 | |
|         internal bool   useSSPI          = false;                                   // use integrated security
 | |
|         internal int    packetSize       = SqlConnectionString.DEFAULT.Packet_Size; // packet size
 | |
|         internal bool   readOnlyIntent   = false;                                   // read-only intent
 | |
|         internal SqlCredential credential;                                          // user id and password in SecureString
 | |
|         internal SecureString newSecurePassword;                                    // new password in SecureString for resetting pasword
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlLoginAck {
 | |
|         internal string programName;
 | |
|         internal byte   majorVersion;
 | |
|         internal byte   minorVersion;
 | |
|         internal short  buildNum;
 | |
|         internal bool   isVersion8;
 | |
|         internal UInt32 tdsVersion;
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlFedAuthInfo {
 | |
|         internal string spn;
 | |
|         internal string stsurl;
 | |
|         public override string ToString() {
 | |
|             return String.Format(CultureInfo.InvariantCulture, "STSURL: {0}, SPN: {1}", stsurl ?? String.Empty, spn ?? String.Empty);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlFedAuthToken {
 | |
|         internal UInt32 dataLen;
 | |
|         internal byte[] accessToken;
 | |
|         internal long expirationFileTime;
 | |
|     }
 | |
| 
 | |
|     sealed internal class _SqlMetaData : SqlMetaDataPriv, ICloneable {
 | |
| 
 | |
|         internal string             column;
 | |
|         internal string             baseColumn;
 | |
|         internal MultiPartTableName multiPartTableName;
 | |
|         internal readonly int       ordinal;
 | |
|         internal byte               updatability;     // two bit field (0 is read only, 1 is updatable, 2 is updatability unknown)
 | |
|         internal byte               tableNum;
 | |
|         internal bool               isDifferentName;
 | |
|         internal bool               isKey;
 | |
|         internal bool               isHidden;
 | |
|         internal bool               isExpression;
 | |
|         internal bool               isIdentity;
 | |
|         internal bool               isColumnSet;
 | |
|         internal byte               op;       // for altrow-columns only
 | |
|         internal ushort             operand;  // for altrow-columns only
 | |
| 
 | |
|         internal _SqlMetaData(int ordinal) : base() {
 | |
|             this.ordinal = ordinal;
 | |
|         }
 | |
| 
 | |
|         internal string serverName {
 | |
|             get {
 | |
|                 return multiPartTableName.ServerName;
 | |
|             }
 | |
|         }
 | |
|         internal string catalogName {
 | |
|             get {
 | |
|                 return multiPartTableName.CatalogName;
 | |
|             }
 | |
|         }
 | |
|         internal string schemaName {
 | |
|             get {
 | |
|                 return multiPartTableName.SchemaName;
 | |
|             }
 | |
|         }
 | |
|         internal string tableName {
 | |
|             get {
 | |
|                 return multiPartTableName.TableName;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal bool IsNewKatmaiDateTimeType {
 | |
|             get {
 | |
|                 return SqlDbType.Date == type || SqlDbType.Time == type || SqlDbType.DateTime2 == type || SqlDbType.DateTimeOffset == type;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal bool IsLargeUdt {
 | |
|             get {
 | |
|                 return type == SqlDbType.Udt && length == Int32.MaxValue;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public object Clone() {
 | |
|             _SqlMetaData result = new _SqlMetaData(ordinal);
 | |
|             result.CopyFrom(this);
 | |
|             result.column = column;
 | |
|             result.baseColumn = baseColumn;
 | |
|             result.multiPartTableName = multiPartTableName;
 | |
|             result.updatability = updatability;
 | |
|             result.tableNum = tableNum;
 | |
|             result.isDifferentName = isDifferentName;
 | |
|             result.isKey = isKey;
 | |
|             result.isHidden = isHidden;
 | |
|             result.isExpression = isExpression;
 | |
|             result.isIdentity = isIdentity;
 | |
|             result.isColumnSet = isColumnSet;
 | |
|             result.op = op;
 | |
|             result.operand = operand;
 | |
|             return result;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class _SqlMetaDataSet : ICloneable {
 | |
|         internal ushort         id;             // for altrow-columns only
 | |
|         internal int[]          indexMap;
 | |
|         internal int            visibleColumns;
 | |
|         internal DataTable      schemaTable;
 | |
|         internal readonly SqlTceCipherInfoTable? cekTable; // table of "column encryption keys" used for this metadataset
 | |
|         internal readonly _SqlMetaData[] metaDataArray;
 | |
| 
 | |
|         internal _SqlMetaDataSet(int count, SqlTceCipherInfoTable? cipherTable) {
 | |
|             cekTable = cipherTable;
 | |
|             metaDataArray = new _SqlMetaData[count];
 | |
|             for(int i = 0; i < metaDataArray.Length; ++i) {
 | |
|                 metaDataArray[i] = new _SqlMetaData(i);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private _SqlMetaDataSet(_SqlMetaDataSet original) {
 | |
|             this.id = original.id;
 | |
|             // although indexMap is not immutable, in practice it is initialized once and then passed around
 | |
|             this.indexMap = original.indexMap;
 | |
|             this.visibleColumns = original.visibleColumns;
 | |
|             this.schemaTable = original.schemaTable;
 | |
|             if (original.metaDataArray == null) {
 | |
|                 metaDataArray = null;
 | |
|             }
 | |
|             else {
 | |
|                 metaDataArray = new _SqlMetaData[original.metaDataArray.Length];
 | |
|                 for (int idx=0; idx<metaDataArray.Length; idx++) {
 | |
|                     metaDataArray[idx] = (_SqlMetaData)original.metaDataArray[idx].Clone();
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal int Length {
 | |
|             get {
 | |
|                 return metaDataArray.Length;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal _SqlMetaData this [int index] {
 | |
|             get {
 | |
|                 return metaDataArray[index];
 | |
|             }
 | |
|             set {
 | |
|                 Debug.Assert(null == value, "used only by SqlBulkCopy");
 | |
|                 metaDataArray[index] = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public object Clone() {
 | |
|             return new _SqlMetaDataSet(this);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class _SqlMetaDataSetCollection : ICloneable {
 | |
|         private readonly List<_SqlMetaDataSet> altMetaDataSetArray;
 | |
|         internal _SqlMetaDataSet metaDataSet;
 | |
| 
 | |
|         internal _SqlMetaDataSetCollection () {
 | |
|             altMetaDataSetArray = new List<_SqlMetaDataSet>();
 | |
|         }
 | |
| 
 | |
|         internal void SetAltMetaData(_SqlMetaDataSet altMetaDataSet) {
 | |
|             // VSTFDEVDIV 479675: if altmetadata with same id is found, override it rather than adding a new one
 | |
|             int newId = altMetaDataSet.id;
 | |
|             for (int i = 0; i < altMetaDataSetArray.Count; i++) {
 | |
|                 if (altMetaDataSetArray[i].id == newId) {
 | |
|                     // override the existing metadata with the same id
 | |
|                     altMetaDataSetArray[i] = altMetaDataSet;
 | |
|                     return;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // if we did not find metadata to override, add as new
 | |
|             altMetaDataSetArray.Add(altMetaDataSet);
 | |
|         }
 | |
| 
 | |
|         internal _SqlMetaDataSet GetAltMetaData(int id) {
 | |
|             foreach (_SqlMetaDataSet altMetaDataSet in altMetaDataSetArray) {
 | |
|                 if (altMetaDataSet.id == id) {
 | |
|                     return altMetaDataSet;
 | |
|                 }
 | |
|             }
 | |
|             Debug.Assert (false, "Can't match up altMetaDataSet with given id");
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         public object Clone()
 | |
|         {
 | |
|             _SqlMetaDataSetCollection result = new _SqlMetaDataSetCollection();
 | |
|             result.metaDataSet = metaDataSet == null ? null : (_SqlMetaDataSet)metaDataSet.Clone();
 | |
|             foreach (_SqlMetaDataSet set in altMetaDataSetArray) {
 | |
|                 result.altMetaDataSetArray.Add((_SqlMetaDataSet)set.Clone());
 | |
|             }
 | |
|             return result;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Represents Encryption related information of the cipher data.
 | |
|     /// </summary>
 | |
|     internal class SqlCipherMetadata {
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Cipher Info Entry.
 | |
|         /// </summary>
 | |
|         private SqlTceCipherInfoEntry? _sqlTceCipherInfoEntry;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Encryption Algorithm Id.
 | |
|         /// </summary>
 | |
|         private readonly byte _cipherAlgorithmId;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Encryption Algorithm Name.
 | |
|         /// </summary>
 | |
|         private readonly string _cipherAlgorithmName;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Encryption Type.
 | |
|         /// </summary>
 | |
|         private readonly byte _encryptionType;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Normalization Rule Version.
 | |
|         /// </summary>
 | |
|         private readonly byte _normalizationRuleVersion;
 | |
|         
 | |
|         /// <summary>
 | |
|         /// Encryption Algorithm Handle.
 | |
|         /// </summary>
 | |
|         private SqlClientEncryptionAlgorithm _sqlClientEncryptionAlgorithm;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Sql Encryption Key Info.
 | |
|         /// </summary>
 | |
|         private SqlEncryptionKeyInfo? _sqlEncryptionKeyInfo;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Ordinal (into the Cek Table).
 | |
|         /// </summary>
 | |
|         private readonly ushort _ordinal;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the Encryption Info Entry.
 | |
|         /// </summary>
 | |
|         internal SqlTceCipherInfoEntry? EncryptionInfo {
 | |
|             get {
 | |
|                 return _sqlTceCipherInfoEntry;
 | |
|             }
 | |
|             set {
 | |
|                 Debug.Assert(!_sqlTceCipherInfoEntry.HasValue, "We can only set the EncryptionInfo once.");
 | |
|                 _sqlTceCipherInfoEntry = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the cipher's encryption algorithm id.
 | |
|         /// </summary>
 | |
|         internal byte CipherAlgorithmId {
 | |
|             get {
 | |
|                 return _cipherAlgorithmId;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the cipher's encryption algorithm name (could be null).
 | |
|         /// </summary>
 | |
|         internal string CipherAlgorithmName {
 | |
|             get {
 | |
|                 return _cipherAlgorithmName;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return EncryptionType (Deterministic, Randomized, etc.)
 | |
|         /// </summary>
 | |
|         internal byte EncryptionType {
 | |
|             get {
 | |
|                 return _encryptionType;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return normalization rule version.
 | |
|         /// </summary>
 | |
|         internal byte NormalizationRuleVersion {
 | |
|             get {
 | |
|                 return _normalizationRuleVersion;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the cipher encyrption algorithm handle.
 | |
|         /// </summary>
 | |
|         internal SqlClientEncryptionAlgorithm CipherAlgorithm {
 | |
|             get {
 | |
|                 return _sqlClientEncryptionAlgorithm;
 | |
|             }
 | |
|             set {
 | |
|                 Debug.Assert(_sqlClientEncryptionAlgorithm == null, "_sqlClientEncryptionAlgorithm should not be set more than once.");
 | |
|                  _sqlClientEncryptionAlgorithm = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return Encryption Key Info.
 | |
|         /// </summary>
 | |
|         internal SqlEncryptionKeyInfo? EncryptionKeyInfo {
 | |
|             get {
 | |
|                 return _sqlEncryptionKeyInfo;
 | |
|             }
 | |
| 
 | |
|             set {
 | |
|                 Debug.Assert(!_sqlEncryptionKeyInfo.HasValue, "_sqlEncryptionKeyInfo should not be set more than once.");
 | |
|                 _sqlEncryptionKeyInfo = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return Ordinal into Cek Table.
 | |
|         /// </summary>
 | |
|         internal ushort CekTableOrdinal {
 | |
|             get {
 | |
|                 return _ordinal;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Constructor.
 | |
|         /// </summary>
 | |
|         /// <param name="sqlTceCipherInfoEntry"></param>
 | |
|         /// <param name="sqlClientEncryptionAlgorithm"></param>
 | |
|         /// <param name="cipherAlgorithmId"></param>
 | |
|         /// <param name="encryptionType"></param>
 | |
|         /// <param name="normalizationRuleVersion"></param>
 | |
|         internal SqlCipherMetadata (SqlTceCipherInfoEntry? sqlTceCipherInfoEntry,
 | |
|                                     ushort ordinal,
 | |
|                                     byte cipherAlgorithmId,
 | |
|                                     string cipherAlgorithmName,
 | |
|                                     byte encryptionType,
 | |
|                                     byte normalizationRuleVersion) {
 | |
|             Debug.Assert(!sqlTceCipherInfoEntry.Equals(default(SqlTceCipherInfoEntry)), "sqlTceCipherInfoEntry should not be un-initialized.");
 | |
| 
 | |
|             _sqlTceCipherInfoEntry = sqlTceCipherInfoEntry;
 | |
|             _ordinal = ordinal;
 | |
|             _cipherAlgorithmId = cipherAlgorithmId;
 | |
|             _cipherAlgorithmName = cipherAlgorithmName;
 | |
|             _encryptionType = encryptionType;
 | |
|             _normalizationRuleVersion = normalizationRuleVersion;
 | |
|             _sqlEncryptionKeyInfo = null;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Do we have an handle to the cipher encryption algorithm already ?
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         internal bool IsAlgorithmInitialized() {
 | |
|             return (null != _sqlClientEncryptionAlgorithm) ? true : false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     internal class SqlMetaDataPriv {
 | |
|         internal SqlDbType    type;    // SqlDbType enum value
 | |
|         internal byte         tdsType; // underlying tds type
 | |
|         internal byte         precision = TdsEnums.UNKNOWN_PRECISION_SCALE; // give default of unknown (-1)
 | |
|         internal byte         scale     = TdsEnums.UNKNOWN_PRECISION_SCALE; // give default of unknown (-1)
 | |
|         internal int          length;
 | |
|         internal SqlCollation collation;
 | |
|         internal int          codePage;
 | |
|         internal Encoding     encoding;
 | |
|         internal bool         isNullable;
 | |
|         internal bool         isMultiValued = false;
 | |
| 
 | |
|         // UDT specific metadata
 | |
|         // server metadata info
 | |
|         // additional temporary UDT meta data
 | |
|         internal string                 udtDatabaseName;
 | |
|         internal string                 udtSchemaName;
 | |
|         internal string                 udtTypeName;
 | |
|         internal string                 udtAssemblyQualifiedName;
 | |
|         // on demand
 | |
|         internal Type                   udtType;
 | |
| 
 | |
|         // Xml specific metadata
 | |
|         internal string       xmlSchemaCollectionDatabase;
 | |
|         internal string       xmlSchemaCollectionOwningSchema;
 | |
|         internal string       xmlSchemaCollectionName;
 | |
|         internal MetaType     metaType; // cached metaType
 | |
| 
 | |
|         // Structured type-specific metadata
 | |
|         internal string                 structuredTypeDatabaseName;
 | |
|         internal string                 structuredTypeSchemaName;
 | |
|         internal string                 structuredTypeName;
 | |
|         internal IList<SmiMetaData>     structuredFields;
 | |
| 
 | |
|         internal bool                    isEncrypted; // TCE encrypted?
 | |
|         internal SqlMetaDataPriv         baseTI;   // for encrypted columns, represents the TYPE_INFO for plaintext value
 | |
|         internal SqlCipherMetadata       cipherMD; // Cipher related metadata for encrypted columns.
 | |
|         internal SqlMetaDataPriv() {
 | |
|         }
 | |
| 
 | |
|         internal virtual void CopyFrom(SqlMetaDataPriv original) {
 | |
|             this.type = original.type;
 | |
|             this.tdsType = original.tdsType;
 | |
|             this.precision = original.precision;
 | |
|             this.scale = original.scale;
 | |
|             this.length = original.length;
 | |
|             this.collation = original.collation;
 | |
|             this.codePage = original.codePage;
 | |
|             this.encoding = original.encoding;
 | |
|             this.isNullable = original.isNullable;
 | |
|             this.isMultiValued = original.isMultiValued;
 | |
|             this.udtDatabaseName = original.udtDatabaseName;
 | |
|             this.udtSchemaName = original.udtSchemaName;
 | |
|             this.udtTypeName = original.udtTypeName;
 | |
|             this.udtAssemblyQualifiedName = original.udtAssemblyQualifiedName;
 | |
|             this.udtType = original.udtType;
 | |
|             this.xmlSchemaCollectionDatabase = original.xmlSchemaCollectionDatabase;
 | |
|             this.xmlSchemaCollectionOwningSchema = original.xmlSchemaCollectionOwningSchema;
 | |
|             this.xmlSchemaCollectionName = original.xmlSchemaCollectionName;
 | |
|             this.metaType = original.metaType;
 | |
|             // 
 | |
| 
 | |
| 
 | |
|             this.structuredTypeDatabaseName = original.structuredTypeDatabaseName;
 | |
|             this.structuredTypeSchemaName = original.structuredTypeSchemaName;
 | |
|             this.structuredTypeName = original.structuredTypeName;
 | |
|             this.structuredFields = original.structuredFields;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Is the algorithm handle for the cipher encryption initialized ?
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         internal bool IsAlgorithmInitialized() {
 | |
|             if (null != cipherMD) {
 | |
|                 return cipherMD.IsAlgorithmInitialized(); 
 | |
|             }
 | |
| 
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Returns the normalization rule version byte.
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         internal byte NormalizationRuleVersion {
 | |
|             get {
 | |
|                 if (null != cipherMD){
 | |
|                     return cipherMD.NormalizationRuleVersion; 
 | |
|                 }
 | |
| 
 | |
|                 return 0x00;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Class encapsulating additional information when sending encrypted input parameters.
 | |
|     /// </summary>
 | |
|     sealed internal class SqlColumnEncryptionInputParameterInfo
 | |
|     {
 | |
|         /// <summary>
 | |
|         /// Metadata of the parameter to write the TYPE_INFO of the unencrypted column data type.
 | |
|         /// </summary>
 | |
|         private readonly SmiParameterMetaData _smiParameterMetadata;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Column encryption related metadata.
 | |
|         /// </summary>
 | |
|         private readonly SqlCipherMetadata _cipherMetadata;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Serialized format for a subset of members.
 | |
|         /// Does not include _smiParameterMetadata's serialization.
 | |
|         /// </summary>
 | |
|         private readonly byte[] _serializedWireFormat;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the SMI Parameter Metadata.
 | |
|         /// </summary>
 | |
|         internal SmiParameterMetaData ParameterMetadata {
 | |
|             get {
 | |
|                 return _smiParameterMetadata;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Return the serialized format for some members.
 | |
|         /// This is pre-calculated and cached since members are immutable.
 | |
|         /// Does not include _smiParameterMetadata's serialization.
 | |
|         /// </summary>
 | |
|         internal byte[] SerializedWireFormat
 | |
|         {
 | |
|             get {
 | |
|                 return _serializedWireFormat;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Constructor.
 | |
|         /// </summary>
 | |
|         /// <param name="smiParameterMetadata"></param>
 | |
|         /// <param name="cipherMetadata"></param>
 | |
|         internal SqlColumnEncryptionInputParameterInfo(SmiParameterMetaData smiParameterMetadata, SqlCipherMetadata cipherMetadata) {
 | |
|             Debug.Assert(smiParameterMetadata != null, "smiParameterMetadata should not be null.");
 | |
|             Debug.Assert(cipherMetadata != null, "cipherMetadata should not be null");
 | |
|             Debug.Assert(cipherMetadata.EncryptionKeyInfo.HasValue, "cipherMetadata.EncryptionKeyInfo.HasValue should be true.");
 | |
| 
 | |
|             _smiParameterMetadata = smiParameterMetadata;
 | |
|             _cipherMetadata = cipherMetadata;
 | |
|             _serializedWireFormat = SerializeToWriteFormat();
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Serializes some data members to wire format.
 | |
|         /// </summary>
 | |
|         private byte[] SerializeToWriteFormat() {
 | |
|             int totalLength = 0;
 | |
| 
 | |
|             // CipherAlgorithmId.
 | |
|             totalLength += sizeof(byte);
 | |
| 
 | |
|             // Encryption Type.
 | |
|             totalLength += sizeof(byte);
 | |
| 
 | |
|             // Database id of the encryption key.
 | |
|             totalLength += sizeof(int);
 | |
| 
 | |
|             // Id of the encryption key.
 | |
|             totalLength += sizeof(int);
 | |
| 
 | |
|             // Version of the encryption key.
 | |
|             totalLength += sizeof(int);
 | |
| 
 | |
|             // Metadata version of the encryption key.
 | |
|             totalLength += _cipherMetadata.EncryptionKeyInfo.Value.cekMdVersion.Length;
 | |
| 
 | |
|             // Normalization Rule Version.
 | |
|             totalLength += sizeof(byte);
 | |
| 
 | |
|             byte[] serializedWireFormat = new byte[totalLength];
 | |
| 
 | |
|             // No:of bytes consumed till now. Running variable.
 | |
|             int consumedBytes = 0;
 | |
| 
 | |
|             // 1 - Write Cipher Algorithm Id.
 | |
|             serializedWireFormat[consumedBytes++] = _cipherMetadata.CipherAlgorithmId;
 | |
| 
 | |
|             // 2 - Write Encryption Type.
 | |
|             serializedWireFormat[consumedBytes++] = _cipherMetadata.EncryptionType;
 | |
| 
 | |
|             // 3 - Write the database id of the encryption key.
 | |
|             SerializeIntIntoBuffer(_cipherMetadata.EncryptionKeyInfo.Value.databaseId, serializedWireFormat, ref consumedBytes);
 | |
| 
 | |
|             // 4 - Write the id of the encryption key.
 | |
|             SerializeIntIntoBuffer(_cipherMetadata.EncryptionKeyInfo.Value.cekId, serializedWireFormat, ref consumedBytes);
 | |
| 
 | |
|             // 5 - Write the version of the encryption key.
 | |
|             SerializeIntIntoBuffer(_cipherMetadata.EncryptionKeyInfo.Value.cekVersion, serializedWireFormat, ref consumedBytes);
 | |
| 
 | |
|             // 6 - Write the metadata version of the encryption key.
 | |
|             Buffer.BlockCopy(_cipherMetadata.EncryptionKeyInfo.Value.cekMdVersion, 0, serializedWireFormat, consumedBytes, _cipherMetadata.EncryptionKeyInfo.Value.cekMdVersion.Length);
 | |
|             consumedBytes += _cipherMetadata.EncryptionKeyInfo.Value.cekMdVersion.Length;
 | |
| 
 | |
|             // 7 - Write Normalization Rule Version.
 | |
|             serializedWireFormat[consumedBytes++] = _cipherMetadata.NormalizationRuleVersion;
 | |
| 
 | |
|             return serializedWireFormat;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Serializes an int into the provided buffer and offset.
 | |
|         /// </summary>
 | |
|         private void SerializeIntIntoBuffer(int value, byte[] buffer, ref int offset) {
 | |
|             buffer[offset++] = (byte)(value & 0xff);
 | |
|             buffer[offset++] = (byte)((value >> 8) & 0xff);
 | |
|             buffer[offset++] = (byte)((value >> 16) & 0xff);
 | |
|             buffer[offset++] = (byte)((value >> 24) & 0xff);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class _SqlRPC {
 | |
|         internal string         rpcName;
 | |
|         internal string         databaseName; // Used for UDTs
 | |
|         internal ushort         ProcID;       // Used instead of name
 | |
|         internal ushort         options;
 | |
|         internal SqlParameter[] parameters;
 | |
|         internal byte[]         paramoptions;
 | |
| 
 | |
|         internal int?           recordsAffected;
 | |
|         internal int            cumulativeRecordsAffected;
 | |
| 
 | |
|         internal int            errorsIndexStart;
 | |
|         internal int            errorsIndexEnd;
 | |
|         internal SqlErrorCollection errors;
 | |
|         
 | |
|         internal int            warningsIndexStart;
 | |
|         internal int            warningsIndexEnd;
 | |
|         internal SqlErrorCollection warnings;
 | |
|         internal bool           needsFetchParameterEncryptionMetadata;
 | |
|         internal string GetCommandTextOrRpcName() {
 | |
|             if (TdsEnums.RPC_PROCID_EXECUTESQL == ProcID) {
 | |
|                 // Param 0 is the actual sql executing
 | |
|                 return (string)parameters[0].Value;
 | |
|             }
 | |
|             else {
 | |
|                 return rpcName;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     sealed internal class SqlReturnValue : SqlMetaDataPriv {
 | |
| 
 | |
|         internal ushort    parmIndex;      //Yukon or later only
 | |
|         internal string    parameter;
 | |
|         internal readonly  SqlBuffer value;
 | |
| 
 | |
|         internal SqlReturnValue() : base() {
 | |
|             value = new SqlBuffer();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     internal struct MultiPartTableName {
 | |
|         private string _multipartName;
 | |
|         private string _serverName;
 | |
|         private string _catalogName;
 | |
|         private string _schemaName;
 | |
|         private string _tableName;
 | |
| 
 | |
|         internal MultiPartTableName(string[] parts) {
 | |
|             _multipartName = null;
 | |
|             _serverName = parts[0];
 | |
|             _catalogName = parts[1];
 | |
|             _schemaName = parts[2];
 | |
|             _tableName = parts[3];
 | |
|         }
 | |
| 
 | |
|         internal MultiPartTableName(string multipartName) {
 | |
|             _multipartName = multipartName;
 | |
|             _serverName = null;
 | |
|             _catalogName = null;
 | |
|             _schemaName = null;
 | |
|             _tableName = null;
 | |
|         }
 | |
| 
 | |
|         internal string ServerName {
 | |
|             get {
 | |
|                 ParseMultipartName();
 | |
|                 return _serverName;
 | |
|             }
 | |
|             set { _serverName = value; }
 | |
|         }
 | |
|         internal string CatalogName {
 | |
|             get {
 | |
|                 ParseMultipartName();
 | |
|                 return _catalogName;
 | |
|             }
 | |
|             set { _catalogName = value; }
 | |
|         }
 | |
|         internal string SchemaName {
 | |
|             get {
 | |
|                 ParseMultipartName();
 | |
|                 return _schemaName;
 | |
|             }
 | |
|             set { _schemaName = value; }
 | |
|         }
 | |
|         internal string TableName {
 | |
|             get {
 | |
|                 ParseMultipartName();
 | |
|                 return _tableName;
 | |
|             }
 | |
|             set { _tableName = value; }
 | |
|         }
 | |
| 
 | |
|         private void ParseMultipartName() {
 | |
|             if (null != _multipartName) {
 | |
|                 string[] parts = MultipartIdentifier.ParseMultipartIdentifier(_multipartName, "[\"", "]\"", Res.SQL_TDSParserTableName, false);
 | |
|                 _serverName = parts[0];
 | |
|                 _catalogName = parts[1];
 | |
|                 _schemaName = parts[2];
 | |
|                 _tableName = parts[3];
 | |
|                 _multipartName = null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         internal static readonly MultiPartTableName Null = new MultiPartTableName(new string[] {null, null, null, null});
 | |
|     }
 | |
| }
 |