internal SqlCachedBuffer(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj)
 {
     int len = 0;
     this._cachedBytes = new ArrayList();
     ulong num = parser.PlpBytesLeft(stateObj);
     do
     {
         if (num == 0L)
         {
             return;
         }
         do
         {
             len = (num > 0x800L) ? 0x800 : ((int) num);
             byte[] buff = new byte[len];
             len = stateObj.ReadPlpBytes(ref buff, 0, len);
             if (this._cachedBytes.Count == 0)
             {
                 this.AddByteOrderMark(buff);
             }
             this._cachedBytes.Add(buff);
             num -= len;
         }
         while (num > 0L);
         num = parser.PlpBytesLeft(stateObj);
     }
     while (num > 0L);
 }
        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;
        }
        internal SqlCachedBuffer(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj)
        {
            int len = 0;

            this._cachedBytes = new ArrayList();
            ulong num = parser.PlpBytesLeft(stateObj);

            do
            {
                if (num == 0L)
                {
                    return;
                }
                do
                {
                    len = (num > 0x800L) ? 0x800 : ((int)num);
                    byte[] buff = new byte[len];
                    len = stateObj.ReadPlpBytes(ref buff, 0, len);
                    if (this._cachedBytes.Count == 0)
                    {
                        this.AddByteOrderMark(buff);
                    }
                    this._cachedBytes.Add(buff);
                    num -= len;
                }while (num > 0L);
                num = parser.PlpBytesLeft(stateObj);
            }while (num > 0L);
        }
Exemple #4
0
 internal static void CheckGetExtendedUDTInfo(SqlMetaDataPriv metaData, bool fThrow)
 {
     if (metaData.udtType == null)
     {
         metaData.udtType = Type.GetType(metaData.udtAssemblyQualifiedName, fThrow);
         if (fThrow && (metaData.udtType == null))
         {
             throw SQL.UDTUnexpectedResult(metaData.udtAssemblyQualifiedName);
         }
     }
 }
Exemple #5
0
 internal object GetUdtValue(object value, SqlMetaDataPriv metaData, bool returnDBNull)
 {
     if (returnDBNull && ADP.IsNull(value))
     {
         return DBNull.Value;
     }
     if (ADP.IsNull(value))
     {
         return metaData.udtType.InvokeMember("Null", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static, null, null, new object[0], CultureInfo.InvariantCulture);
     }
     MemoryStream s = new MemoryStream((byte[]) value);
     return SerializationHelperSql9.Deserialize(s, metaData.udtType);
 }
        // Reads off from the network buffer and caches bytes. Only reads one column value in the current row.
        internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer)
        {
            int   cb = 0;
            ulong plplength;

            byte[] byteArr;

            List <byte[]> cachedBytes = new List <byte[]>();

            buffer = null;

            // the very first length is already read.
            if (!parser.TryPlpBytesLeft(stateObj, out plplength))
            {
                return(false);
            }
            // For now we  only handle Plp data from the parser directly.
            Debug.Assert(metadata.metaType.IsPlp, "SqlCachedBuffer call on a non-plp data");
            do
            {
                if (plplength == 0)
                {
                    break;
                }
                do
                {
                    cb      = (plplength > (ulong)_maxChunkSize) ? _maxChunkSize : (int)plplength;
                    byteArr = new byte[cb];
                    if (!stateObj.TryReadPlpBytes(ref byteArr, 0, cb, out cb))
                    {
                        return(false);
                    }
                    Debug.Assert(cb == byteArr.Length);
                    if (cachedBytes.Count == 0)
                    {
                        // Add the Byte order mark if needed if we read the first array
                        AddByteOrderMark(byteArr, cachedBytes);
                    }
                    cachedBytes.Add(byteArr);
                    plplength -= (ulong)cb;
                } while (plplength > 0);
                if (!parser.TryPlpBytesLeft(stateObj, out plplength))
                {
                    return(false);
                }
            } while (plplength > 0);
            Debug.Assert(stateObj._longlen == 0 && stateObj._longlenleft == 0);

            buffer = new SqlCachedBuffer(cachedBytes);
            return(true);
        }
 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.xmlSchemaCollectionDatabase = original.xmlSchemaCollectionDatabase;
     this.xmlSchemaCollectionOwningSchema = original.xmlSchemaCollectionOwningSchema;
     this.xmlSchemaCollectionName = original.xmlSchemaCollectionName;
     this.metaType = original.metaType;
 }
Exemple #8
0
        // Reads off from the network buffer and caches bytes. Only reads one column value in the current row.
        static internal bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer)
        {
            int cb = 0;
            ulong plplength;
            byte[] byteArr;

            List<byte[]> cachedBytes = new List<byte[]>();
            buffer = null;

            // the very first length is already read.
            if (!parser.TryPlpBytesLeft(stateObj, out plplength))
            {
                return false;
            }
            // For now we  only handle Plp data from the parser directly.
            Debug.Assert(metadata.metaType.IsPlp, "SqlCachedBuffer call on a non-plp data");
            do
            {
                if (plplength == 0)
                    break;
                do
                {
                    cb = (plplength > (ulong)_maxChunkSize) ? _maxChunkSize : (int)plplength;
                    byteArr = new byte[cb];
                    if (!stateObj.TryReadPlpBytes(ref byteArr, 0, cb, out cb))
                    {
                        return false;
                    }
                    Debug.Assert(cb == byteArr.Length);
                    if (cachedBytes.Count == 0)
                    {
                        // Add the Byte order mark if needed if we read the first array
                        AddByteOrderMark(byteArr, cachedBytes);
                    }
                    cachedBytes.Add(byteArr);
                    plplength -= (ulong)cb;
                } while (plplength > 0);
                if (!parser.TryPlpBytesLeft(stateObj, out plplength))
                {
                    return false;
                }
            } while (plplength > 0);
            Debug.Assert(stateObj._longlen == 0 && stateObj._longlenleft == 0);

            buffer = new SqlCachedBuffer(cachedBytes);
            return true;
        }
 internal object GetUdtValue(object value, SqlMetaDataPriv metaData, bool returnDBNull)
 => throw new PlatformNotSupportedException(EXCEPTION_MESSAGE);
Exemple #10
0
        private bool TryProcessColumnHeaderNoNBC(SqlMetaDataPriv col, TdsParserStateObject stateObj, out bool isNull, out ulong length)
        {
            if (col.metaType.IsLong && !col.metaType.IsPlp)
            {
                //
                // we don't care about TextPtrs, simply go after the data after it
                //
                byte textPtrLen;
                if (!stateObj.TryReadByte(out textPtrLen))
                {
                    isNull = false;
                    length = 0;
                    return false;
                }

                if (0 != textPtrLen)
                {
                    // read past text pointer
                    if (!stateObj.TrySkipBytes(textPtrLen))
                    {
                        isNull = false;
                        length = 0;
                        return false;
                    }

                    // read past timestamp
                    if (!stateObj.TrySkipBytes(TdsEnums.TEXT_TIME_STAMP_LEN))
                    {
                        isNull = false;
                        length = 0;
                        return false;
                    }

                    isNull = false;
                    return TryGetDataLength(col, stateObj, out length);
                }
                else
                {
                    isNull = true;
                    length = 0;
                    return true;
                }
            }
            else
            {
                // non-blob columns
                ulong longlen;
                if (!TryGetDataLength(col, stateObj, out longlen))
                {
                    isNull = false;
                    length = 0;
                    return false;
                }
                isNull = IsNull(col.metaType, longlen);
                length = (isNull ? 0 : longlen);
                return true;
            }
        }
 internal void SkipValue(SqlMetaDataPriv md, TdsParserStateObject stateObj)
 {
     if (md.metaType.IsPlp)
     {
         this.SkipPlpValue(ulong.MaxValue, stateObj);
     }
     else
     {
         int tokenLength = this.GetTokenLength(md.tdsType, stateObj);
         if (!this.IsNull(md.metaType, (ulong) tokenLength))
         {
             this.SkipBytes(tokenLength, stateObj);
         }
     }
 }
 internal void CheckGetExtendedUDTInfo(SqlMetaDataPriv metaData, bool fThrow)
 => throw new PlatformNotSupportedException(EXCEPTION_MESSAGE);
 private void ProcessUDTMetaData(SqlMetaDataPriv metaData, TdsParserStateObject stateObj)
 {
     metaData.length = stateObj.ReadUInt16();
     int length = stateObj.ReadByte();
     if (length != 0)
     {
         metaData.udtDatabaseName = stateObj.ReadString(length);
     }
     length = stateObj.ReadByte();
     if (length != 0)
     {
         metaData.udtSchemaName = stateObj.ReadString(length);
     }
     length = stateObj.ReadByte();
     if (length != 0)
     {
         metaData.udtTypeName = stateObj.ReadString(length);
     }
     length = stateObj.ReadUInt16();
     if (length != 0)
     {
         metaData.udtAssemblyQualifiedName = stateObj.ReadString(length);
     }
 }
Exemple #14
0
         private bool TryProcessUDTMetaData(SqlMetaDataPriv metaData, TdsParserStateObject stateObj) {

            ushort shortLength;
            byte byteLength;

            if (!stateObj.TryReadUInt16(out shortLength)) { // max byte size
                return false;
            }
            metaData.length = shortLength;

            // database name
            if (!stateObj.TryReadByte(out byteLength)) {
                return false;
            }
            if (byteLength != 0) {
                if (!stateObj.TryReadString(byteLength, out metaData.udtDatabaseName)) {
                    return false;
                }
            }

            // schema name
            if (!stateObj.TryReadByte(out byteLength)) {
                return false;
            }
            if (byteLength != 0) {
                if (!stateObj.TryReadString(byteLength, out metaData.udtSchemaName)) {
                    return false;
                }
            }

            // type name
            if (!stateObj.TryReadByte(out byteLength)) {
                return false;
            }
            if (byteLength != 0) {
                if (!stateObj.TryReadString(byteLength, out metaData.udtTypeName)) {
                    return false;
                }
            }

            if (!stateObj.TryReadUInt16(out shortLength)) {
                return false;
            }
            if (shortLength != 0) {
                if (!stateObj.TryReadString(shortLength, out metaData.udtAssemblyQualifiedName)) {
                    return false;
                }
            }

            return true;
        }       
Exemple #15
0
 //
 // Returns the data stream length of the data identified by tds type or SqlMetaData returns
 // Returns either the total size or the size of the first chunk for partially length prefixed types.
 //
 internal bool TryGetDataLength(SqlMetaDataPriv colmeta, TdsParserStateObject stateObj, out ulong length)
 {
     // Handle Yukon specific tokens
     if (colmeta.metaType.IsPlp)
     {
         Debug.Assert(colmeta.tdsType == TdsEnums.SQLXMLTYPE ||
                      colmeta.tdsType == TdsEnums.SQLBIGVARCHAR ||
                      colmeta.tdsType == TdsEnums.SQLBIGVARBINARY ||
                      colmeta.tdsType == TdsEnums.SQLNVARCHAR ||
                      // Large UDTs is WinFS-only
                      colmeta.tdsType == TdsEnums.SQLUDT,
                      "GetDataLength:Invalid streaming datatype");
         return stateObj.TryReadPlpLength(true, out length);
     }
     else
     {
         int intLength;
         if (!TryGetTokenLength(colmeta.tdsType, stateObj, out intLength))
         {
             length = 0;
             return false;
         }
         length = (ulong)intLength;
         return true;
     }
 }
Exemple #16
0
        internal int ReadPlpAnsiChars(ref char[] buff, int offst, int len, SqlMetaDataPriv metadata, TdsParserStateObject stateObj)
        {
            int charsRead = 0;
            int charsLeft = 0;
            int bytesRead = 0;
            int totalcharsRead = 0;

            if (stateObj._longlen == 0)
            {
                Debug.Assert(stateObj._longlenleft == 0);
                return 0;       // No data
            }

            Debug.Assert(((ulong)stateObj._longlen != TdsEnums.SQL_PLP_NULL),
                    "Out of sync plp read request");

            Debug.Assert((buff == null && offst == 0) || (buff.Length >= offst + len), "Invalid length sent to ReadPlpAnsiChars()!");
            charsLeft = len;

            if (stateObj._longlenleft == 0)
            {
                stateObj.ReadPlpLength(false);
                if (stateObj._longlenleft == 0)
                {// Data read complete
                    stateObj._plpdecoder = null;
                    return 0;
                }
            }

            if (stateObj._plpdecoder == null)
            {
                Encoding enc = metadata.encoding;

                if (enc == null)
                {
                    if (null == _defaultEncoding)
                    {
                        ThrowUnsupportedCollationEncountered(stateObj);
                    }

                    enc = _defaultEncoding;
                }
                stateObj._plpdecoder = enc.GetDecoder();
            }

            while (charsLeft > 0)
            {
                bytesRead = (int)Math.Min(stateObj._longlenleft, (ulong)charsLeft);
                if ((stateObj._bTmp == null) || (stateObj._bTmp.Length < bytesRead))
                {
                    // Grow the array
                    stateObj._bTmp = new byte[bytesRead];
                }

                bytesRead = stateObj.ReadPlpBytesChunk(stateObj._bTmp, 0, bytesRead);

                charsRead = stateObj._plpdecoder.GetChars(stateObj._bTmp, 0, bytesRead, buff, offst);
                charsLeft -= charsRead;
                offst += charsRead;
                totalcharsRead += charsRead;
                if (stateObj._longlenleft == 0)  // Read the next chunk or cleanup state if hit the end
                    stateObj.ReadPlpLength(false);

                if (stateObj._longlenleft == 0)
                { // Data read complete
                    stateObj._plpdecoder = null;
                    break;
                }
            }
            return (totalcharsRead);
        }
        internal void ReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, int length, TdsParserStateObject stateObj)
        {
            if (md.metaType.IsPlp)
            {
                length = 0x7fffffff;
            }
            switch (md.tdsType)
            {
                case 0x22:
                case 0x25:
                case 0x2d:
                case 240:
                case 0xa5:
                case 0xad:
                {
                    byte[] buff = null;
                    if (md.metaType.IsPlp)
                    {
                        stateObj.ReadPlpBytes(ref buff, 0, length);
                    }
                    else
                    {
                        buff = new byte[length];
                        stateObj.ReadByteArray(buff, 0, length);
                    }
                    value.SqlBinary = new SqlBinary(buff, true);
                    return;
                }
                case 0x23:
                case 0x27:
                case 0x2f:
                case 0x63:
                case 0xef:
                case 0xe7:
                case 0xa7:
                case 0xaf:
                    this.ReadSqlStringValue(value, md.tdsType, length, md.encoding, md.metaType.IsPlp, stateObj);
                    return;

                case 40:
                case 0x29:
                case 0x2a:
                case 0x2b:
                    this.ReadSqlDateTime(value, md.tdsType, length, md.scale, stateObj);
                    return;

                case 0x6a:
                case 0x6c:
                    this.ReadSqlDecimal(value, length, md.precision, md.scale, stateObj);
                    return;

                case 0xf1:
                {
                    SqlCachedBuffer buffer2 = new SqlCachedBuffer(md, this, stateObj);
                    value.SqlCachedBuffer = buffer2;
                    return;
                }
            }
            this.ReadSqlValueInternal(value, md.tdsType, md.metaType.TypeId, length, stateObj);
        }
Exemple #18
0
        /// <summary>
        /// This method skips bytes of a single column value from the media. It supports NBCROW and handles all types of values, including PLP and long
        /// </summary>
        internal bool TrySkipValue(SqlMetaDataPriv md, int columnOrdinal, TdsParserStateObject stateObj)
        {
            if (stateObj.IsNullCompressionBitSet(columnOrdinal))
            {
                return true;
            }

            if (md.metaType.IsPlp)
            {
                ulong ignored;
                if (!TrySkipPlpValue(UInt64.MaxValue, stateObj, out ignored))
                {
                    return false;
                }
            }
            else if (md.metaType.IsLong)
            {
                Debug.Assert(!md.metaType.IsPlp, "Plp types must be handled using SkipPlpValue");

                byte textPtrLen;
                if (!stateObj.TryReadByte(out textPtrLen))
                {
                    return false;
                }

                if (0 != textPtrLen)
                {
                    if (!stateObj.TrySkipBytes(textPtrLen + TdsEnums.TEXT_TIME_STAMP_LEN))
                    {
                        return false;
                    }

                    int length;
                    if (!TryGetTokenLength(md.tdsType, stateObj, out length))
                    {
                        return false;
                    }
                    if (!stateObj.TrySkipBytes(length))
                    {
                        return false;
                    }
                }
            }
            else
            {
                int length;
                if (!TryGetTokenLength(md.tdsType, stateObj, out length))
                {
                    return false;
                }

                // if false, no value to skip - it's null
                if (!IsNull(md.metaType, (ulong)length))
                {
                    if (!stateObj.TrySkipBytes(length))
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        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;
        }
        internal bool TryProcessTceCryptoMetadata (TdsParserStateObject stateObj, 
            SqlMetaDataPriv col, 
            SqlTceCipherInfoTable? cipherTable, 
            SqlCommandColumnEncryptionSetting columnEncryptionSetting,
            bool isReturnValue) {
            Debug.Assert(isReturnValue == (cipherTable == null), "Ciphertable is not set iff this is a return value");

            // Read the ordinal into cipher table
            ushort index = 0;
            UInt32 userType;

            // For return values there is not cipher table and no ordinal.
            if (cipherTable.HasValue) {
                if (!stateObj.TryReadUInt16(out index)) {
                    return false;
                }

                // validate the index (ordinal passed)
                if (index >= cipherTable.Value.Size) {
                    Bid.Trace("<sc.TdsParser.TryProcessTceCryptoMetadata|TCE> Incorrect ordinal received %d, max tab size: %d\n", index, cipherTable.Value.Size);
                    throw SQL.ParsingErrorValue(ParsingErrorState.TceInvalidOrdinalIntoCipherInfoTable, index);
                }
            }

            // Read the user type
            if (!stateObj.TryReadUInt32(out userType)) {
                return false;
            }

            // Read the base TypeInfo
            col.baseTI = new SqlMetaDataPriv();
            if (!TryProcessTypeInfo(stateObj, col.baseTI, userType)) {
                return false;
            }

            // Read the cipher algorithm Id
            byte cipherAlgorithmId;
            if (!stateObj.TryReadByte(out cipherAlgorithmId)) {
                return false;
            }

            string cipherAlgorithmName = null;
            if (TdsEnums.CustomCipherAlgorithmId == cipherAlgorithmId) {
                // Custom encryption algorithm, read the name
                byte nameSize;
                if (!stateObj.TryReadByte(out nameSize)) {
                    return false;
                }

                if (!stateObj.TryReadString(nameSize, out cipherAlgorithmName)) {
                    return false;
                }
            }

            // Read Encryption Type. 
            byte encryptionType;
            if (!stateObj.TryReadByte(out encryptionType)) {
                return false;
            }

            // Read Normalization Rule Version.
            byte normalizationRuleVersion;
            if (!stateObj.TryReadByte(out normalizationRuleVersion)) {
                return false;
            }

            Debug.Assert(col.cipherMD == null, "col.cipherMD should be null in TryProcessTceCryptoMetadata.");

            // Check if TCE is enable and if it is set the crypto MD for the column.
            // TCE is enabled if the command is set to enabled or to resultset only and this is not a return value
            // or if it is set to use connection setting and the connection has TCE enabled.
            if ((columnEncryptionSetting == SqlCommandColumnEncryptionSetting.Enabled ||
                (columnEncryptionSetting == SqlCommandColumnEncryptionSetting.ResultSetOnly && !isReturnValue)) ||
                (columnEncryptionSetting == SqlCommandColumnEncryptionSetting.UseConnectionSetting &&
                _connHandler != null && _connHandler.ConnectionOptions != null &&
                _connHandler.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled)) {
                col.cipherMD = new SqlCipherMetadata(cipherTable.HasValue ? (SqlTceCipherInfoEntry?)cipherTable.Value[index] : null,
                                                        index,
                                                        cipherAlgorithmId: cipherAlgorithmId,
                                                        cipherAlgorithmName: cipherAlgorithmName,
                                                        encryptionType: encryptionType,
                                                        normalizationRuleVersion: normalizationRuleVersion);
            }
            else {
                // If TCE is disabled mark the MD as not encrypted.
                col.isEncrypted = false;
            }

            return true;
        }
        internal void WriteBulkCopyValue(object value, SqlMetaDataPriv metadata, TdsParserStateObject stateObj)
        {
            MetaType metaType = metadata.metaType;
            ulong length = 0L;
            ulong byteCount = 0L;
            if (ADP.IsNull(value))
            {
                if (metaType.IsPlp && ((metaType.NullableType != 240) || metaType.IsLong))
                {
                    this.WriteLong(-1L, stateObj);
                }
                else if ((!metaType.IsFixed && !metaType.IsLong) && !metaType.IsVarTime)
                {
                    this.WriteShort(0xffff, stateObj);
                }
                else
                {
                    this.WriteByte(0, stateObj);
                }
            }
            else
            {
                switch (metaType.NullableType)
                {
                    case 0x22:
                    case 0xa5:
                    case 0xad:
                    case 240:
                        length = (value is byte[]) ? ((ulong) ((byte[]) value).Length) : ((ulong) ((SqlBinary) value).Length);
                        break;

                    case 0x23:
                    case 0xa7:
                    case 0xaf:
                        if (this._defaultEncoding == null)
                        {
                            this.ThrowUnsupportedCollationEncountered(null);
                        }
                        if (value is string)
                        {
                            length = (ulong) ((string) value).Length;
                            byteCount = (ulong) this._defaultEncoding.GetByteCount((string) value);
                        }
                        else
                        {
                            SqlString str4 = (SqlString) value;
                            length = (ulong) str4.Value.Length;
                            SqlString str3 = (SqlString) value;
                            byteCount = (ulong) this._defaultEncoding.GetByteCount(str3.Value);
                        }
                        break;

                    case 0x24:
                        length = 0x10L;
                        break;

                    case 0x63:
                    case 0xe7:
                    case 0xef:
                        length = (ulong) (((value is string) ? ((long) ((string) value).Length) : ((long) ((SqlString) value).Value.Length)) * 2L);
                        break;

                    case 0xf1:
                        if (value is XmlReader)
                        {
                            value = MetaType.GetStringFromXml((XmlReader) value);
                        }
                        length = (ulong) (((value is string) ? ((long) ((string) value).Length) : ((long) ((SqlString) value).Value.Length)) * 2L);
                        break;

                    default:
                        length = (ulong) metadata.length;
                        break;
                }
                if (metaType.IsLong)
                {
                    switch (metaType.SqlDbType)
                    {
                        case SqlDbType.NText:
                        case SqlDbType.Image:
                        case SqlDbType.Text:
                            this.WriteByteArray(s_longDataHeader, s_longDataHeader.Length, 0, stateObj);
                            this.WriteTokenLength(metadata.tdsType, (byteCount == 0L) ? ((int) length) : ((int) byteCount), stateObj);
                            break;

                        case SqlDbType.NVarChar:
                        case SqlDbType.VarBinary:
                        case SqlDbType.VarChar:
                        case SqlDbType.Xml:
                        case SqlDbType.Udt:
                            this.WriteUnsignedLong(18446744073709551614L, stateObj);
                            break;
                    }
                }
                else
                {
                    this.WriteTokenLength(metadata.tdsType, (byteCount == 0L) ? ((int) length) : ((int) byteCount), stateObj);
                }
                if (DataStorage.IsSqlType(value.GetType()))
                {
                    this.WriteSqlValue(value, metaType, (int) length, (int) byteCount, 0, stateObj);
                }
                else if ((metaType.SqlDbType != SqlDbType.Udt) || metaType.IsLong)
                {
                    this.WriteValue(value, metaType, metadata.scale, (int) length, (int) byteCount, 0, stateObj);
                }
                else
                {
                    this.WriteShort((int) length, stateObj);
                    this.WriteByteArray((byte[]) value, (int) length, 0, stateObj);
                }
            }
        }
 internal ulong GetDataLength(SqlMetaDataPriv colmeta, TdsParserStateObject stateObj)
 {
     if (this._isYukon && colmeta.metaType.IsPlp)
     {
         return stateObj.ReadPlpLength(true);
     }
     return (ulong) this.GetTokenLength(colmeta.tdsType, stateObj);
 }
        internal object GetNullSqlValue(SqlBuffer nullVal, SqlMetaDataPriv md)
        {
            switch (md.type)
            {
                case SqlDbType.BigInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int64);
                    return nullVal;

                case SqlDbType.Binary:
                case SqlDbType.Image:
                case SqlDbType.VarBinary:
                case SqlDbType.Udt:
                    nullVal.SqlBinary = SqlBinary.Null;
                    return nullVal;

                case SqlDbType.Bit:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Boolean);
                    return nullVal;

                case SqlDbType.Char:
                case SqlDbType.NChar:
                case SqlDbType.NText:
                case SqlDbType.NVarChar:
                case SqlDbType.Text:
                case SqlDbType.VarChar:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.String);
                    return nullVal;

                case SqlDbType.DateTime:
                case SqlDbType.SmallDateTime:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime);
                    return nullVal;

                case SqlDbType.Decimal:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Decimal);
                    return nullVal;

                case SqlDbType.Float:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Double);
                    return nullVal;

                case SqlDbType.Int:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int32);
                    return nullVal;

                case SqlDbType.Money:
                case SqlDbType.SmallMoney:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Money);
                    return nullVal;

                case SqlDbType.Real:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Single);
                    return nullVal;

                case SqlDbType.UniqueIdentifier:
                    nullVal.SqlGuid = SqlGuid.Null;
                    return nullVal;

                case SqlDbType.SmallInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int16);
                    return nullVal;

                case SqlDbType.Timestamp:
                case (SqlDbType.SmallInt | SqlDbType.Int):
                case (SqlDbType.Text | SqlDbType.Int):
                case (SqlDbType.Xml | SqlDbType.Bit):
                case (SqlDbType.TinyInt | SqlDbType.Int):
                case SqlDbType.Structured:
                    return nullVal;

                case SqlDbType.TinyInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Byte);
                    return nullVal;

                case SqlDbType.Variant:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Empty);
                    return nullVal;

                case SqlDbType.Xml:
                    nullVal.SqlCachedBuffer = SqlCachedBuffer.Null;
                    return nullVal;

                case SqlDbType.Date:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Date);
                    return nullVal;

                case SqlDbType.Time:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Time);
                    return nullVal;

                case SqlDbType.DateTime2:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime2);
                    return nullVal;

                case SqlDbType.DateTimeOffset:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTimeOffset);
                    return nullVal;
            }
            return nullVal;
        }
        private bool TryProcessTypeInfo (TdsParserStateObject stateObj, SqlMetaDataPriv col, UInt32 userType) {
            byte byteLen;
            byte tdsType;
            if (!stateObj.TryReadByte(out tdsType)) {
                return false;
            }

            if (tdsType == TdsEnums.SQLXMLTYPE)
                col.length = TdsEnums.SQL_USHORTVARMAXLEN;  //Use the same length as other plp datatypes
            else if (IsVarTimeTds(tdsType))
                col.length = 0;  // placeholder until we read the scale, just make sure it's not SQL_USHORTVARMAXLEN
            else if (tdsType == TdsEnums.SQLDATE) {
                col.length = 3;
            }
            else {
                if (!TryGetTokenLength(tdsType, stateObj, out col.length)) {
                    return false;
                }
            }

            col.metaType = MetaType.GetSqlDataType(tdsType, userType, col.length);
            col.type = col.metaType.SqlDbType;

            // If sphinx, do not change to nullable type
            if (_isShiloh)
                col.tdsType = (col.isNullable ? col.metaType.NullableType : col.metaType.TDSType);
            else
                col.tdsType = tdsType;

            if (_isYukon) {
                if (TdsEnums.SQLUDT == tdsType) {
                    if (!TryProcessUDTMetaData((SqlMetaDataPriv) col, stateObj)) {
                        return false;
                    }
                }

                if (col.length == TdsEnums.SQL_USHORTVARMAXLEN) {
                    Debug.Assert(tdsType == TdsEnums.SQLXMLTYPE ||
                                 tdsType == TdsEnums.SQLBIGVARCHAR ||
                                 tdsType == TdsEnums.SQLBIGVARBINARY ||
                                 tdsType == TdsEnums.SQLNVARCHAR ||
                                 tdsType == TdsEnums.SQLUDT,
                                 "Invalid streaming datatype");
                    col.metaType = MetaType.GetMaxMetaTypeFromMetaType(col.metaType);
                    Debug.Assert(col.metaType.IsLong, "Max datatype not IsLong");
                    col.length = Int32.MaxValue;
                    if (tdsType == TdsEnums.SQLXMLTYPE) {
                        byte schemapresent;
                        if (!stateObj.TryReadByte(out schemapresent)) {
                            return false;
                        }

                        if ((schemapresent & 1) != 0) {
                            if (!stateObj.TryReadByte(out byteLen)) {
                                return false;
                            }
                            if (byteLen != 0) {
                                if (!stateObj.TryReadString(byteLen, out col.xmlSchemaCollectionDatabase)) {
                                    return false;
                                }
                            }

                            if (!stateObj.TryReadByte(out byteLen)) {
                                return false;
                            }
                            if (byteLen != 0) {
                                if (!stateObj.TryReadString(byteLen, out col.xmlSchemaCollectionOwningSchema)) {
                                    return false;
                                }
                            }

                            short shortLen;
                            if (!stateObj.TryReadInt16(out shortLen)) {
                                return false;
                            }
                            if (byteLen != 0) {
                                if (!stateObj.TryReadString(shortLen, out col.xmlSchemaCollectionName)) {
                                    return false;
                                }
                            }
                        }
                    }
                }
            }

            if (col.type == SqlDbType.Decimal) {
                if (!stateObj.TryReadByte(out col.precision)) {
                    return false;
                }
                if (!stateObj.TryReadByte(out col.scale)) {
                    return false;
                }
            }

            if (col.metaType.IsVarTime) {
                if (!stateObj.TryReadByte(out col.scale)) {
                    return false;
                }

                Debug.Assert(0 <= col.scale && col.scale <= 7);

                // calculate actual column length here
                // 
                switch (col.metaType.SqlDbType)
                {
                    case SqlDbType.Time:
                        col.length = MetaType.GetTimeSizeFromScale(col.scale);
                        break;
                    case SqlDbType.DateTime2:
                        // Date in number of days (3 bytes) + time
                        col.length = 3 + MetaType.GetTimeSizeFromScale(col.scale);
                        break;
                    case SqlDbType.DateTimeOffset:
                        // Date in days (3 bytes) + offset in minutes (2 bytes) + time
                        col.length = 5 + MetaType.GetTimeSizeFromScale(col.scale);
                        break;

                    default:
                        Debug.Assert(false, "Unknown VariableTime type!");
                        break;
                }
            }

            // read the collation for 7.x servers
            if (_isShiloh && col.metaType.IsCharType && (tdsType != TdsEnums.SQLXMLTYPE)) {
                if (!TryProcessCollation(stateObj, out col.collation)) {
                    return false;
                }

                int codePage = GetCodePage(col.collation, stateObj);

                if (codePage == _defaultCodePage) {
                    col.codePage = _defaultCodePage;
                    col.encoding = _defaultEncoding;
                }
                else {
                    col.codePage = codePage;
                    col.encoding = System.Text.Encoding.GetEncoding(col.codePage);
                }
            }

            return true;
        }
 internal int ReadPlpAnsiChars(ref char[] buff, int offst, int len, SqlMetaDataPriv metadata, TdsParserStateObject stateObj)
 {
     int num3 = 0;
     int num2 = 0;
     int num = 0;
     int num4 = 0;
     if (stateObj._longlen == 0L)
     {
         return 0;
     }
     num2 = len;
     if (stateObj._longlenleft == 0L)
     {
         stateObj.ReadPlpLength(false);
         if (stateObj._longlenleft == 0L)
         {
             return 0;
         }
     }
     Encoding encoding = metadata.encoding;
     if (encoding == null)
     {
         if (this._defaultEncoding == null)
         {
             this.ThrowUnsupportedCollationEncountered(stateObj);
         }
         encoding = this._defaultEncoding;
     }
     while (num2 > 0)
     {
         num = (int) Math.Min(stateObj._longlenleft, (ulong) num2);
         if ((stateObj._bTmp == null) || (stateObj._bTmp.Length < num))
         {
             stateObj._bTmp = new byte[num];
         }
         num = stateObj.ReadPlpBytesChunk(stateObj._bTmp, 0, num);
         num3 = encoding.GetChars(stateObj._bTmp, 0, num, buff, offst);
         num2 -= num3;
         offst += num3;
         num4 += num3;
         if (stateObj._longlenleft == 0L)
         {
             stateObj.ReadPlpLength(false);
         }
         if (stateObj._longlenleft == 0L)
         {
             return num4;
         }
     }
     return num4;
 }
Exemple #26
0
        // takes care of any per data header information:
        // for long columns, reads off textptrs, reads length, check nullability
        // for other columns, reads length, checks nullability
        // returns length and nullability
        internal bool TryProcessColumnHeader(SqlMetaDataPriv col, TdsParserStateObject stateObj, int columnOrdinal, out bool isNull, out ulong length)
        {
            // query NBC row information first
            if (stateObj.IsNullCompressionBitSet(columnOrdinal))
            {
                isNull = true;
                // column information is not present in TDS if null compression bit is set, return now
                length = 0;
                return true;
            }

            return TryProcessColumnHeaderNoNBC(col, stateObj, out isNull, out length);
        }
        internal static object GetNullSqlValue(
                SqlBuffer nullVal, 
                SqlMetaDataPriv md, 
                SqlCommandColumnEncryptionSetting columnEncryptionSetting,
                SqlInternalConnectionTds connection) {
            SqlDbType type = md.type;

            if (type == SqlDbType.VarBinary && // if its a varbinary
                md.isEncrypted &&// and encrypted
                ShouldHonorTceForRead(columnEncryptionSetting, connection)){
                type = md.baseTI.type; // the use the actual (plaintext) type
            }

            switch (type) {
                case SqlDbType.Real:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Single);
                    break;

                case SqlDbType.Float:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Double);
                    break;

                case SqlDbType.Udt:
                case SqlDbType.Binary:
                case SqlDbType.VarBinary:
                case SqlDbType.Image:
                    nullVal.SqlBinary = SqlBinary.Null;
                    break;

                case SqlDbType.UniqueIdentifier:
                    nullVal.SqlGuid = SqlGuid.Null;
                    break;

                case SqlDbType.Bit:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Boolean);
                    break;

                case SqlDbType.TinyInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Byte);
                    break;

                case SqlDbType.SmallInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int16);
                    break;

                case SqlDbType.Int:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int32);
                    break;

                case SqlDbType.BigInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int64);
                    break;

                case SqlDbType.Char:
                case SqlDbType.VarChar:
                case SqlDbType.NChar:
                case SqlDbType.NVarChar:
                case SqlDbType.Text:
                case SqlDbType.NText:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.String);
                    break;

                case SqlDbType.Decimal:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Decimal);
                    break;

                case SqlDbType.DateTime:
                case SqlDbType.SmallDateTime:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime);
                    break;

                case SqlDbType.Money:
                case SqlDbType.SmallMoney:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Money);
                    break;

                case SqlDbType.Variant:
                    // DBNull.Value will have to work here
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Empty);
                    break;

                case SqlDbType.Xml:
                    nullVal.SqlCachedBuffer = SqlCachedBuffer.Null;
                    break;

                case SqlDbType.Date:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Date);
                    break;

                case SqlDbType.Time:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Time);
                    break;
                    
                case SqlDbType.DateTime2:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime2);
                    break;
                    
                case SqlDbType.DateTimeOffset:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTimeOffset);
                    break;

                case SqlDbType.Timestamp:
                    // Dev10 Bug #479607 - this should have been the same as SqlDbType.Binary, but it's a rejected breaking change
                    // Dev10 Bug #752790 - don't assert when it does happen
                    break;

                default:
                    Debug.Assert(false, "unknown null sqlType!" + md.type.ToString());
                    break;
            }

            return nullVal;
        }
Exemple #28
0
        internal object GetNullSqlValue(SqlBuffer nullVal, SqlMetaDataPriv md)
        {
            switch (md.type)
            {
                case SqlDbType.Real:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Single);
                    break;

                case SqlDbType.Float:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Double);
                    break;

                case SqlDbType.Udt:
                case SqlDbType.Binary:
                case SqlDbType.VarBinary:
                case SqlDbType.Image:
                    nullVal.SqlBinary = SqlBinary.Null;
                    break;

                case SqlDbType.UniqueIdentifier:
                    nullVal.SqlGuid = SqlGuid.Null;
                    break;

                case SqlDbType.Bit:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Boolean);
                    break;

                case SqlDbType.TinyInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Byte);
                    break;

                case SqlDbType.SmallInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int16);
                    break;

                case SqlDbType.Int:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int32);
                    break;

                case SqlDbType.BigInt:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Int64);
                    break;

                case SqlDbType.Char:
                case SqlDbType.VarChar:
                case SqlDbType.NChar:
                case SqlDbType.NVarChar:
                case SqlDbType.Text:
                case SqlDbType.NText:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.String);
                    break;

                case SqlDbType.Decimal:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Decimal);
                    break;

                case SqlDbType.DateTime:
                case SqlDbType.SmallDateTime:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime);
                    break;

                case SqlDbType.Money:
                case SqlDbType.SmallMoney:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Money);
                    break;

                case SqlDbType.Variant:
                    // DBNull.Value will have to work here
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Empty);
                    break;

                case SqlDbType.Xml:
                    nullVal.SqlCachedBuffer = SqlCachedBuffer.Null;
                    break;

                case SqlDbType.Date:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Date);
                    break;

                case SqlDbType.Time:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.Time);
                    break;

                case SqlDbType.DateTime2:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTime2);
                    break;

                case SqlDbType.DateTimeOffset:
                    nullVal.SetToNullOfType(SqlBuffer.StorageType.DateTimeOffset);
                    break;

                case SqlDbType.Timestamp:
                    break;

                default:
                    Debug.Assert(false, "unknown null sqlType!" + md.type.ToString());
                    break;
            }

            return nullVal;
        }
        /// <summary>
        /// Deserializes the unencrypted bytes into a value based on the target type info.
        /// </summary>
        internal bool DeserializeUnencryptedValue (SqlBuffer value, byte[] unencryptedBytes, SqlMetaDataPriv md, TdsParserStateObject stateObj, byte normalizationVersion) {
            if (normalizationVersion != 0x01) {
                throw SQL.UnsupportedNormalizationVersion(normalizationVersion);
            }

            byte tdsType = md.baseTI.tdsType;
            int length = unencryptedBytes.Length;

            // For normalized types, the length and scale of the actual type might be different than the value's.
            int denormalizedLength = md.baseTI.length;
            byte denormalizedScale = md.baseTI.scale;

            Debug.Assert (false == md.baseTI.isEncrypted, "Double encryption detected");
            switch (tdsType) {
                // We normalize to allow conversion across data types. All data types below are serialized into a BIGINT.
                case TdsEnums.SQLBIT:
                case TdsEnums.SQLBITN:
                case TdsEnums.SQLINTN:
                case TdsEnums.SQLINT1:
                case TdsEnums.SQLINT2:
                case TdsEnums.SQLINT4:
                case TdsEnums.SQLINT8:
                    Debug.Assert(length == 8, "invalid length for SqlInt64 type!");
                    byte byteValue;
                    long longValue;

                    if (unencryptedBytes.Length != 8) {
                        return false;
                    }

                    longValue = BitConverter.ToInt64(unencryptedBytes, 0);

                    if (tdsType == TdsEnums.SQLBIT ||
                        tdsType == TdsEnums.SQLBITN) {
                        value.Boolean = (longValue != 0);
                        break;
                    }

                    if (tdsType == TdsEnums.SQLINT1 || denormalizedLength == 1)
                        value.Byte = (byte)longValue;
                    else if (tdsType == TdsEnums.SQLINT2 || denormalizedLength == 2)
                        value.Int16 = (Int16)longValue;
                    else if (tdsType == TdsEnums.SQLINT4 || denormalizedLength == 4)
                        value.Int32 = (Int32)longValue;
                    else
                        value.Int64 = longValue;

                    break;

                case TdsEnums.SQLFLTN:
                    if (length == 4) {
                        goto case TdsEnums.SQLFLT4;
                    }
                    else {
                        goto case TdsEnums.SQLFLT8;
                    }

                case TdsEnums.SQLFLT4:
                    Debug.Assert(length == 4, "invalid length for SqlSingle type!");
                    float singleValue;
                    if (unencryptedBytes.Length != 4) {
                        return false;
                    }

                    singleValue = BitConverter.ToSingle(unencryptedBytes, 0);
                    value.Single = singleValue;
                    break;

                case TdsEnums.SQLFLT8:
                    double doubleValue;
                    if (unencryptedBytes.Length != 8) {
                        return false;
                    }

                    doubleValue = BitConverter.ToDouble(unencryptedBytes, 0);
                    value.Double = doubleValue;
                    break;

                // We normalize to allow conversion across data types. SMALLMONEY is serialized into a MONEY.
                case TdsEnums.SQLMONEYN:
                case TdsEnums.SQLMONEY4:
                case TdsEnums.SQLMONEY:
                {
                    int mid;
                    uint lo;

                    if (unencryptedBytes.Length != 8) {
                        return false;
                    }

                    mid = BitConverter.ToInt32(unencryptedBytes, 0);
                    lo = BitConverter.ToUInt32(unencryptedBytes, 4);

                    long l = (((long)mid) << 0x20) + ((long)lo);
                    value.SetToMoney(l);
                    break;
                }

                case TdsEnums.SQLDATETIMN:
                    if (length == 4) {
                        goto case TdsEnums.SQLDATETIM4;
                    }
                    else {
                        goto case TdsEnums.SQLDATETIME;
                    }

                case TdsEnums.SQLDATETIM4:
                    ushort daypartShort, timepartShort;
                    if (unencryptedBytes.Length != 4) {
                        return false;
                    }

                    daypartShort = (UInt16)((unencryptedBytes[1] << 8) + unencryptedBytes[0]);
                    timepartShort = (UInt16)((unencryptedBytes[3] << 8) + unencryptedBytes[2]);
                    value.SetToDateTime(daypartShort, timepartShort * SqlDateTime.SQLTicksPerMinute);
                    break;

                case TdsEnums.SQLDATETIME:
                    int daypart;
                    uint timepart;
                    if (unencryptedBytes.Length != 8) {
                        return false;
                    }

                    daypart = BitConverter.ToInt32(unencryptedBytes, 0);
                    timepart = BitConverter.ToUInt32(unencryptedBytes, 4);
                    value.SetToDateTime(daypart, (int)timepart);
                    break;

                case TdsEnums.SQLUNIQUEID:
                {
                    Debug.Assert(length == 16, "invalid length for SqlGuid type!");
                    value.SqlGuid = new SqlGuid(unencryptedBytes, true);   // doesn't copy the byte array
                    break;
                }

                case TdsEnums.SQLBINARY:
                case TdsEnums.SQLBIGBINARY:
                case TdsEnums.SQLBIGVARBINARY:
                case TdsEnums.SQLVARBINARY:
                case TdsEnums.SQLIMAGE:
                {
                    // Note: Better not come here with plp data!!
                    Debug.Assert(length <= TdsEnums.MAXSIZE, "Plp data decryption attempted");

                    // If this is a fixed length type, pad with zeros to get to the fixed length size.
                    if (tdsType == TdsEnums.SQLBINARY || tdsType == TdsEnums.SQLBIGBINARY) {
                        byte[] bytes = new byte[md.baseTI.length];
                        Buffer.BlockCopy(unencryptedBytes, 0, bytes, 0, unencryptedBytes.Length);
                        unencryptedBytes = bytes;
                    }

                    value.SqlBinary = new SqlBinary(unencryptedBytes, true);   // doesn't copy the byte array
                    break;
                }

                case TdsEnums.SQLDECIMALN:
                case TdsEnums.SQLNUMERICN:
                    // Check the sign from the first byte.
                    int index = 0;
                    byteValue = unencryptedBytes[index++];
                    bool fPositive = (1 == byteValue);

                    // Now read the 4 next integers which contain the actual value.
                    length = checked((int)length-1);
                    int[] bits = new int[4];
                    int decLength = length>>2;
                    for (int i = 0; i < decLength; i++) {
                        // up to 16 bytes of data following the sign byte
                        bits[i] = BitConverter.ToInt32(unencryptedBytes, index);
                        index += 4;
                    }
                    value.SetToDecimal (md.baseTI.precision, md.baseTI.scale, fPositive, bits);
                    break;

                case TdsEnums.SQLCHAR:
                case TdsEnums.SQLBIGCHAR:
                case TdsEnums.SQLVARCHAR:
                case TdsEnums.SQLBIGVARCHAR:
                case TdsEnums.SQLTEXT:
                    {
                        System.Text.Encoding encoding = md.baseTI.encoding;

                        if (null == encoding) {
                            encoding = _defaultEncoding;
                        }

                        if (null == encoding) {
                            ThrowUnsupportedCollationEncountered(stateObj);
                        }

                        string strValue = encoding.GetString(unencryptedBytes, 0, length);

                        // If this is a fixed length type, pad with spaces to get to the fixed length size.
                        if (tdsType == TdsEnums.SQLCHAR || tdsType == TdsEnums.SQLBIGCHAR) {
                            strValue = strValue.PadRight(md.baseTI.length);
                        }

                        value.SetToString(strValue);
                        break;
                    }

                case TdsEnums.SQLNCHAR:
                case TdsEnums.SQLNVARCHAR:
                case TdsEnums.SQLNTEXT:
                    {
                        string strValue = System.Text.Encoding.Unicode.GetString(unencryptedBytes, 0, length);

                        // If this is a fixed length type, pad with spaces to get to the fixed length size.
                        if (tdsType == TdsEnums.SQLNCHAR) {
                            strValue = strValue.PadRight(md.baseTI.length / ADP.CharSize);
                        }

                        value.SetToString(strValue);
                        break;
                    }

                case TdsEnums.SQLDATE:
                    Debug.Assert(length == 3, "invalid length for date type!");
                    value.SetToDate(unencryptedBytes);
                    break;

                case TdsEnums.SQLTIME:
                    // We normalize to maximum precision to allow conversion across different precisions.
                    Debug.Assert(length == 5, "invalid length for time type!");
                    value.SetToTime(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale);
                    break;

                case TdsEnums.SQLDATETIME2:
                    // We normalize to maximum precision to allow conversion across different precisions.
                    Debug.Assert(length == 8, "invalid length for datetime2 type!");
                    value.SetToDateTime2(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale);
                    break;

                case TdsEnums.SQLDATETIMEOFFSET:
                    // We normalize to maximum precision to allow conversion across different precisions.
                    Debug.Assert(length == 10, "invalid length for datetimeoffset type!");
                    value.SetToDateTimeOffset(unencryptedBytes, length, TdsEnums.MAX_TIME_SCALE, denormalizedScale);
                    break;

                default:
                    MetaType metaType = md.baseTI.metaType;

                    // If we don't have a metatype already, construct one to get the proper type name.
                    if (metaType == null) {
                        metaType = MetaType.GetSqlDataType(tdsType, userType:0, length:length);
                    }

                    throw SQL.UnsupportedDatatypeEncryption(metaType.TypeName);
            }

            return true;
        }
Exemple #30
0
        internal bool TryReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, int length, TdsParserStateObject stateObj)
        {
            bool isPlp = md.metaType.IsPlp;
            byte tdsType = md.tdsType;

            Debug.Assert(isPlp || !IsNull(md.metaType, (ulong)length), "null value should not get here!");
            if (isPlp)
            {
                // We must read the column value completely, no matter what length is passed in
                length = Int32.MaxValue;
            }
            switch (tdsType)
            {
                case TdsEnums.SQLDECIMALN:
                case TdsEnums.SQLNUMERICN:
                    if (!TryReadSqlDecimal(value, length, md.precision, md.scale, stateObj))
                    {
                        return false;
                    }
                    break;

                case TdsEnums.SQLUDT:
                    throw SQL.UnsupportedFeatureAndToken(_connHandler, SqlDbType.Udt.ToString());
                case TdsEnums.SQLBINARY:
                case TdsEnums.SQLBIGBINARY:
                case TdsEnums.SQLBIGVARBINARY:
                case TdsEnums.SQLVARBINARY:
                case TdsEnums.SQLIMAGE:
                    byte[] b = null;

                    // If varbinary(max), we only read the first chunk here, expecting the caller to read the rest
                    if (isPlp)
                    {
                        // If we are given -1 for length, then we read the entire value,
                        // otherwise only the requested amount, usually first chunk.
                        int ignored;
                        if (!stateObj.TryReadPlpBytes(ref b, 0, length, out ignored))
                        {
                            return false;
                        }
                    }
                    else
                    {
                        //Debug.Assert(length > 0 && length < (long)(Int32.MaxValue), "Bad length for column");
                        b = new byte[length];
                        if (!stateObj.TryReadByteArray(b, 0, length))
                        {
                            return false;
                        }
                    }

                    value.SqlBinary = new SqlBinary(b, true);   // doesn't copy the byte array

                    break;

                case TdsEnums.SQLCHAR:
                case TdsEnums.SQLBIGCHAR:
                case TdsEnums.SQLVARCHAR:
                case TdsEnums.SQLBIGVARCHAR:
                case TdsEnums.SQLTEXT:
                case TdsEnums.SQLNCHAR:
                case TdsEnums.SQLNVARCHAR:
                case TdsEnums.SQLNTEXT:
                    if (!TryReadSqlStringValue(value, tdsType, length, md.encoding, isPlp, stateObj))
                    {
                        return false;
                    }
                    break;

                case TdsEnums.SQLXMLTYPE:
                    // We store SqlCachedBuffer here, so that we can return either SqlBinary, SqlString or SqlXmlReader.
                    SqlCachedBuffer sqlBuf;
                    if (!SqlCachedBuffer.TryCreate(md, this, stateObj, out sqlBuf))
                    {
                        return false;
                    }

                    value.SqlCachedBuffer = sqlBuf;
                    break;

                case TdsEnums.SQLDATE:
                case TdsEnums.SQLTIME:
                case TdsEnums.SQLDATETIME2:
                case TdsEnums.SQLDATETIMEOFFSET:
                    if (!TryReadSqlDateTime(value, tdsType, length, md.scale, stateObj))
                    {
                        return false;
                    }
                    break;

                default:
                    Debug.Assert(!isPlp, "ReadSqlValue calling ReadSqlValueInternal with plp data");
                    if (!TryReadSqlValueInternal(value, tdsType, length, stateObj))
                    {
                        return false;
                    }
                    break;
            }

            Debug.Assert((stateObj._longlen == 0) && (stateObj._longlenleft == 0), "ReadSqlValue did not read plp field completely, longlen =" + stateObj._longlen.ToString((IFormatProvider)null) + ",longlenleft=" + stateObj._longlenleft.ToString((IFormatProvider)null));
            return true;
        }
        internal bool TryReadSqlValue(SqlBuffer value,
                                      SqlMetaDataPriv md,
                                      int length,
                                      TdsParserStateObject stateObj,
                                      SqlCommandColumnEncryptionSetting columnEncryptionOverride, 
                                      string columnName) {
            bool isPlp = md.metaType.IsPlp;
            byte tdsType = md.tdsType;

            Debug.Assert(isPlp || !IsNull(md.metaType, (ulong)length), "null value should not get here!");
            if (isPlp) {
                // We must read the column value completely, no matter what length is passed in
                length = Int32.MaxValue;
            }

            //DEVNOTE: When modifying the following routines (for deserialization) please pay attention to 
            // deserialization code in DecryptWithKey () method and modify it accordingly.
            switch (tdsType) {
                case TdsEnums.SQLDECIMALN:
                case TdsEnums.SQLNUMERICN:
                    if (!TryReadSqlDecimal(value, length, md.precision, md.scale, stateObj)) {
                        return false;
                    }
                    break;

                case TdsEnums.SQLUDT:
                case TdsEnums.SQLBINARY:
                case TdsEnums.SQLBIGBINARY:
                case TdsEnums.SQLBIGVARBINARY:
                case TdsEnums.SQLVARBINARY:
                case TdsEnums.SQLIMAGE:
                    byte[] b = null;

                    // If varbinary(max), we only read the first chunk here, expecting the caller to read the rest
                    if (isPlp) {
                        // If we are given -1 for length, then we read the entire value,
                        // otherwise only the requested amount, usually first chunk.
                        int ignored;
                        if (!stateObj.TryReadPlpBytes(ref b, 0, length, out ignored)) {
                            return false;
                        }
                    }
                    else {
                        //Debug.Assert(length > 0 && length < (long)(Int32.MaxValue), "Bad length for column");
                        b = new byte[length];
                        if (!stateObj.TryReadByteArray(b, 0, length)) {
                            return false;
                        }
                    }

                    if (md.isEncrypted 
                        && ((columnEncryptionOverride == SqlCommandColumnEncryptionSetting.Enabled
                            || columnEncryptionOverride == SqlCommandColumnEncryptionSetting.ResultSetOnly)
                            || (columnEncryptionOverride == SqlCommandColumnEncryptionSetting.UseConnectionSetting
                                && _connHandler != null && _connHandler.ConnectionOptions != null
                                && _connHandler.ConnectionOptions.ColumnEncryptionSetting == SqlConnectionColumnEncryptionSetting.Enabled))) {
                        try {
                            // CipherInfo is present, decrypt and read
                            byte[] unencryptedBytes = SqlSecurityUtility.DecryptWithKey(b, md.cipherMD, _connHandler.ConnectionOptions.DataSource);

                            if (unencryptedBytes != null) {
                                DeserializeUnencryptedValue(value, unencryptedBytes, md, stateObj, md.NormalizationRuleVersion);
                            }
                        }
                        catch (Exception e) {
                            throw SQL.ColumnDecryptionFailed(columnName, null, e);
                        }
                    }
                    else {
                        value.SqlBinary = new SqlBinary(b, true);   // doesn't copy the byte array
                    }
                    break;

                case TdsEnums.SQLCHAR:
                case TdsEnums.SQLBIGCHAR:
                case TdsEnums.SQLVARCHAR:
                case TdsEnums.SQLBIGVARCHAR:
                case TdsEnums.SQLTEXT:
                case TdsEnums.SQLNCHAR:
                case TdsEnums.SQLNVARCHAR:
                case TdsEnums.SQLNTEXT:
                    if (!TryReadSqlStringValue(value, tdsType, length, md.encoding, isPlp, stateObj)) {
                        return false;
                    }
                    break;

                case TdsEnums.SQLXMLTYPE:
                    // We store SqlCachedBuffer here, so that we can return either SqlBinary, SqlString or SqlXmlReader.
                    SqlCachedBuffer sqlBuf;
                    if (!SqlCachedBuffer.TryCreate(md, this, stateObj, out sqlBuf)) {
                        return false;
                    }

                    value.SqlCachedBuffer = sqlBuf;
                    break;

                case TdsEnums.SQLDATE:
                case TdsEnums.SQLTIME: 
                case TdsEnums.SQLDATETIME2:
                case TdsEnums.SQLDATETIMEOFFSET:
                    if (!TryReadSqlDateTime(value, tdsType, length, md.scale, stateObj)) {
                        return false;
                    }
                    break;
                    
                default:
                    Debug.Assert(!isPlp, "ReadSqlValue calling ReadSqlValueInternal with plp data");
                    if (!TryReadSqlValueInternal(value, tdsType, length, stateObj)) {
                        return false;
                    }
                    break;
            }

            Debug.Assert((stateObj._longlen == 0) && (stateObj._longlenleft == 0), "ReadSqlValue did not read plp field completely, longlen =" + stateObj._longlen.ToString((IFormatProvider)null) + ",longlenleft=" + stateObj._longlenleft.ToString((IFormatProvider)null));
            return true;
        }
Exemple #32
0
        internal Task WriteBulkCopyValue(object value, SqlMetaDataPriv metadata, TdsParserStateObject stateObj, bool isSqlType, bool isDataFeed, bool isNull)
        {
            Debug.Assert(!isSqlType || value is INullable, "isSqlType is true, but value can not be type cast to an INullable");
            Debug.Assert(!isDataFeed ^ value is DataFeed, "Incorrect value for isDataFeed");

            Encoding saveEncoding = _defaultEncoding;
            SqlCollation saveCollation = _defaultCollation;
            int saveCodePage = _defaultCodePage;
            int saveLCID = _defaultLCID;
            Task resultTask = null;
            Task internalWriteTask = null;

            if (!(State == TdsParserState.OpenNotLoggedIn || State == TdsParserState.OpenLoggedIn))
            {
                throw ADP.ClosedConnectionError();
            }
            try
            {
                if (metadata.encoding != null)
                {
                    _defaultEncoding = metadata.encoding;
                }
                if (metadata.collation != null)
                {
                    _defaultCollation = metadata.collation;
                    _defaultLCID = _defaultCollation.LCID;
                }
                _defaultCodePage = metadata.codePage;

                MetaType metatype = metadata.metaType;
                int ccb = 0;
                int ccbStringBytes = 0;

                if (isNull)
                {
                    // For UDT, remember we treat as binary even though it is a PLP
                    if (metatype.IsPlp && (metatype.NullableType != TdsEnums.SQLUDT || metatype.IsLong))
                    {
                        WriteLong(unchecked((long)TdsEnums.SQL_PLP_NULL), stateObj);
                    }
                    else if (!metatype.IsFixed && !metatype.IsLong && !metatype.IsVarTime)
                    {
                        WriteShort(TdsEnums.VARNULL, stateObj);
                    }
                    else
                    {
                        stateObj.WriteByte(TdsEnums.FIXEDNULL);
                    }
                    return resultTask;
                }

                if (!isDataFeed)
                {
                    switch (metatype.NullableType)
                    {
                        case TdsEnums.SQLBIGBINARY:
                        case TdsEnums.SQLBIGVARBINARY:
                        case TdsEnums.SQLIMAGE:
                        case TdsEnums.SQLUDT:
                            ccb = (isSqlType) ? ((SqlBinary)value).Length : ((byte[])value).Length;
                            break;
                        case TdsEnums.SQLUNIQUEID:
                            ccb = GUID_SIZE;   // that's a constant for guid
                            break;
                        case TdsEnums.SQLBIGCHAR:
                        case TdsEnums.SQLBIGVARCHAR:
                        case TdsEnums.SQLTEXT:
                            if (null == _defaultEncoding)
                            {
                                ThrowUnsupportedCollationEncountered(null); // stateObject only when reading
                            }

                            string stringValue = null;
                            if (isSqlType)
                            {
                                stringValue = ((SqlString)value).Value;
                            }
                            else
                            {
                                stringValue = (string)value;
                            }

                            ccb = stringValue.Length;
                            ccbStringBytes = _defaultEncoding.GetByteCount(stringValue);
                            break;
                        case TdsEnums.SQLNCHAR:
                        case TdsEnums.SQLNVARCHAR:
                        case TdsEnums.SQLNTEXT:
                            ccb = ((isSqlType) ? ((SqlString)value).Value.Length : ((string)value).Length) * 2;
                            break;
                        case TdsEnums.SQLXMLTYPE:
                            // Value here could be string or XmlReader
                            if (value is XmlReader)
                            {
                                value = MetaType.GetStringFromXml((XmlReader)value);
                            }
                            ccb = ((isSqlType) ? ((SqlString)value).Value.Length : ((string)value).Length) * 2;
                            break;

                        default:
                            ccb = metadata.length;
                            break;
                    }
                }
                else
                {
                    Debug.Assert(metatype.IsLong &&
                        ((metatype.SqlDbType == SqlDbType.VarBinary && value is StreamDataFeed) ||
                         ((metatype.SqlDbType == SqlDbType.VarChar || metatype.SqlDbType == SqlDbType.NVarChar) && value is TextDataFeed) ||
                         (metatype.SqlDbType == SqlDbType.Xml && value is XmlDataFeed)),
                   "Stream data feed should only be assigned to VarBinary(max), Text data feed should only be assigned to [N]VarChar(max), Xml data feed should only be assigned to XML(max)");
                }


                // Expected the text length in data stream for bulk copy of text, ntext, or image data.
                //
                if (metatype.IsLong)
                {
                    switch (metatype.SqlDbType)
                    {
                        case SqlDbType.Text:
                        case SqlDbType.NText:
                        case SqlDbType.Image:
                            stateObj.WriteByteArray(s_longDataHeader, s_longDataHeader.Length, 0);
                            WriteTokenLength(metadata.tdsType, ccbStringBytes == 0 ? ccb : ccbStringBytes, stateObj);
                            break;

                        case SqlDbType.VarChar:
                        case SqlDbType.NVarChar:
                        case SqlDbType.VarBinary:
                        case SqlDbType.Xml:
                        case SqlDbType.Udt:
                            // plp data
                            WriteUnsignedLong(TdsEnums.SQL_PLP_UNKNOWNLEN, stateObj);
                            break;
                    }
                }
                else
                {
                    WriteTokenLength(metadata.tdsType, ccbStringBytes == 0 ? ccb : ccbStringBytes, stateObj);
                }

                if (isSqlType)
                {
                    internalWriteTask = WriteSqlValue(value, metatype, ccb, ccbStringBytes, 0, stateObj);
                }
                else if (metatype.SqlDbType != SqlDbType.Udt || metatype.IsLong)
                {
                    internalWriteTask = WriteValue(value, metatype, metadata.scale, ccb, ccbStringBytes, 0, stateObj, metadata.length, isDataFeed);
                    if ((internalWriteTask == null) && (_asyncWrite))
                    {
                        internalWriteTask = stateObj.WaitForAccumulatedWrites();
                    }
                    Debug.Assert(_asyncWrite || stateObj.WaitForAccumulatedWrites() == null, "Should not have accumulated writes when writing sync");
                }
                else
                {
                    WriteShort(ccb, stateObj);
                    internalWriteTask = stateObj.WriteByteArray((byte[])value, ccb, 0);
                }

#if DEBUG
                //In DEBUG mode, when SetAlwaysTaskOnWrite is true, we create a task. Allows us to verify async execution paths.
                if (_asyncWrite && internalWriteTask == null && SqlBulkCopy.SetAlwaysTaskOnWrite == true)
                {
                    internalWriteTask = Task.FromResult<object>(null);
                }
#endif
                if (internalWriteTask != null)
                { //i.e. the write was async.
                    resultTask = WriteBulkCopyValueSetupContinuation(internalWriteTask, saveEncoding, saveCollation, saveCodePage, saveLCID);
                }
            }
            finally
            {
                if (internalWriteTask == null)
                {
                    _defaultEncoding = saveEncoding;
                    _defaultCollation = saveCollation;
                    _defaultCodePage = saveCodePage;
                    _defaultLCID = saveLCID;
                }
            }
            return resultTask;
        }
        /// <summary>
        /// Writes the UserType and TYPE_INFO values for CryptoMetadata (for bulk copy).
        /// </summary>
        /// <returns></returns>
        internal void WriteTceUserTypeAndTypeInfo(SqlMetaDataPriv mdPriv, TdsParserStateObject stateObj) {
            // Write the UserType (4 byte value)
            WriteInt(0x0, stateObj); // TODO: fix this- timestamp columns have 0x50 value here

            Debug.Assert(SqlDbType.Xml != mdPriv.type);
            Debug.Assert(SqlDbType.Udt != mdPriv.type);

            stateObj.WriteByte(mdPriv.tdsType);

            switch (mdPriv.type) {
                case SqlDbType.Decimal:
                    WriteTokenLength(mdPriv.tdsType, mdPriv.length, stateObj);
                    stateObj.WriteByte(mdPriv.precision);
                    stateObj.WriteByte(mdPriv.scale);
                    break;
                case SqlDbType.Date:
                    // Nothing more to write!
                    break;
                case SqlDbType.Time:
                case SqlDbType.DateTime2:
                case SqlDbType.DateTimeOffset:
                    stateObj.WriteByte(mdPriv.scale);
                    break;
                default:
                    WriteTokenLength(mdPriv.tdsType, mdPriv.length, stateObj);
                    if (mdPriv.metaType.IsCharType && _isShiloh) {
                        WriteUnsignedInt(mdPriv.collation.info, stateObj);
                        stateObj.WriteByte(mdPriv.collation.sortId);
                    }
                    break;
            }
        }
        /// <summary>
        /// Encrypts a column value (for SqlBulkCopy) 
        /// </summary>
        /// <returns></returns>
        internal object EncryptColumnValue (object value, SqlMetaDataPriv metadata, string column, TdsParserStateObject stateObj, bool isDataFeed, bool isSqlType) {
            Debug.Assert (_serverSupportsColumnEncryption, "Server doesn't support encryption, yet we received encryption metadata");
            Debug.Assert (ShouldEncryptValuesForBulkCopy(), "Encryption attempted when not requested");

            if (isDataFeed) { // can't encrypt a stream column
                SQL.StreamNotSupportOnEncryptedColumn(column);
            }

            int actualLengthInBytes;
            switch(metadata.baseTI.metaType.NullableType) {
                case TdsEnums.SQLBIGBINARY:
                case TdsEnums.SQLBIGVARBINARY:
                case TdsEnums.SQLIMAGE:
                    // For some datatypes, engine does truncation before storing the value. (For example, when
                    // trying to insert a varbinary(7000) into a varbinary(3000) column). Since we encrypt the
                    // column values, engine has no way to tell the size of the plaintext datatype. Therefore,
                    // we truncate the values based on target column sizes here before encrypting them. This 
                    // truncation is only needed if we exceed the max column length or if the target column is
                    // not a blob type (eg. varbinary(max)). The actual work of truncating the column happens
                    // when we normalize and serialize the data buffers. The serialization routine expects us 
                    // to report the size of data to be copied out (for serialization). If we underreport the
                    // size, truncation will happen for us!
                    actualLengthInBytes = (isSqlType) ? ((SqlBinary)value).Length : ((byte[])value).Length;
                    if (metadata.baseTI.length > 0 &&
                        actualLengthInBytes > metadata.baseTI.length) { // see comments agove
                        actualLengthInBytes = metadata.baseTI.length;
                    }
                    break;

                case TdsEnums.SQLUNIQUEID:
                    actualLengthInBytes = GUID_SIZE;   // that's a constant for guid
                    break;
                case TdsEnums.SQLBIGCHAR:
                case TdsEnums.SQLBIGVARCHAR:
                case TdsEnums.SQLTEXT:
                    if (null == _defaultEncoding)
                    {
                        ThrowUnsupportedCollationEncountered(null); // stateObject only when reading
                    }

                    string stringValue = (isSqlType) ? ((SqlString)value).Value : (string)value;
                    actualLengthInBytes = _defaultEncoding.GetByteCount(stringValue);

                    // If the string length is > max length, then use the max length (see comments above)
                    if (metadata.baseTI.length > 0 && 
                        actualLengthInBytes > metadata.baseTI.length) {
                        actualLengthInBytes = metadata.baseTI.length; // this ensure truncation!
                    }

                    break;
                case TdsEnums.SQLNCHAR:
                case TdsEnums.SQLNVARCHAR:
                case TdsEnums.SQLNTEXT:
                    actualLengthInBytes = ((isSqlType) ? ((SqlString)value).Value.Length : ((string)value).Length) * 2;

                    if (metadata.baseTI.length > 0 &&
                        actualLengthInBytes > metadata.baseTI.length) { // see comments above
                        actualLengthInBytes = metadata.baseTI.length;
                    }

                    break;

                default:
                    actualLengthInBytes = metadata.baseTI.length;
                    break;
            }

            byte[] serializedValue;
            if (isSqlType) {
                // SqlType
                serializedValue = SerializeUnencryptedSqlValue (value, 
                                            metadata.baseTI.metaType, 
                                            actualLengthInBytes,
                                            offset : 0, 
                                            normalizationVersion: metadata.cipherMD.NormalizationRuleVersion, 
                                            stateObj: stateObj);
            }
            else {
                serializedValue = SerializeUnencryptedValue (value,
                                            metadata.baseTI.metaType, 
                                            metadata.baseTI.scale,
                                            actualLengthInBytes, 
                                            offset: 0, 
                                            isDataFeed: isDataFeed, 
                                            normalizationVersion: metadata.cipherMD.NormalizationRuleVersion, 
                                            stateObj: stateObj);
            }

            Debug.Assert(serializedValue != null, "serializedValue should not be null in TdsExecuteRPC.");
            return SqlSecurityUtility.EncryptWithKey(
                    serializedValue, 
                    metadata.cipherMD, 
                    _connHandler.ConnectionOptions.DataSource);
        }
 internal ulong ProcessColumnHeader(SqlMetaDataPriv col, TdsParserStateObject stateObj, out bool isNull)
 {
     if (col.metaType.IsLong && !col.metaType.IsPlp)
     {
         byte num = stateObj.ReadByte();
         if (num != 0)
         {
             this.SkipBytes(num, stateObj);
             this.SkipBytes(8, stateObj);
             isNull = false;
             return this.GetDataLength(col, stateObj);
         }
         isNull = true;
         return 0L;
     }
     ulong dataLength = this.GetDataLength(col, stateObj);
     isNull = this.IsNull(col.metaType, dataLength);
     if (!isNull)
     {
         return dataLength;
     }
     return 0L;
 }