UInt64 DoneRowCount;               // read 4 bytes if TDS > 7.1, otherwise, read 2 bytes

        public void Read(TDSReader r)
        {
            if (r.TDSVersion == (UInt32)TDSVersions.Unknown)
            {
                throw new UnknownTDSVersionException("Done token needs to know the TDS version.");
            }
            Status = r.ReadUInt16();
            CurCmd = r.ReadUInt16();
            byte TDSVer = (byte)(r.TDSVersion & 0x000000FF);

            DoneRowCount = (TDSVer < 0x72) ? r.ReadUInt32() : r.ReadUInt64();
            r.TokenDone();
        }
        public void Read(TDSReader r)
        {
            byte   MajorVer;
            byte   MinorVer;
            ushort Build;

            Length = r.ReadUInt16();
            r.TokenStart(Length);
            Interface      = r.ReadByte();
            TDSVersion     = r.ReadUInt32();
            r.TDSVersion   = TDSVersion;
            ProgramName    = r.ReadUnicodeString1();
            MajorVer       = r.ReadByte();
            MinorVer       = r.ReadByte();
            Build          = r.ReadUInt16();
            ProgramVersion = MajorVer + "." + MinorVer + "." + Build;
            r.TokenDone();
        }
 public void Read(TDSReader r)
 {
     Length = r.ReadUInt16();
     r.TokenStart(Length);
     Number        = r.ReadUInt32();
     State         = r.ReadByte();
     Class         = r.ReadByte();
     Message       = r.ReadUnicodeString2();
     ServerName    = r.ReadUnicodeString1();
     ProcedureName = r.ReadUnicodeString1();
     LineNumber    = r.ReadUInt32();
     r.TokenDone();
 }
        public void Read(TDSReader r, int headerLength)
        {
            int    ReadLength = 4;
            ushort IDLength;
            ushort DeploymentLength;

            IDLength         = r.ReadUInt16();
            NotifyID         = r.ReadUnicodeString(IDLength / 2);         // IDLength is supposed to be BYTEs rather than Characters - according to the spec
            DeploymentLength = r.ReadUInt16();
            SSBDeployment    = r.ReadUnicodeString(DeploymentLength / 2); // spec section 2.2.5.3.1 (p33/195) says it is a count of bytes not chars
            ReadLength      += 4 + IDLength + DeploymentLength;           // multiply these guys by 2 if it turns out they a char counts - but spec says bytes
            if (ReadLength == headerLength - 4)
            {
                fHasTimeout   = true;
                NotifyTimeout = r.ReadUInt32();
                ReadLength   += 4;
            }
            if (ReadLength != headerLength)
            {
                throw new InvalidTDSException("Query notification header length (" + headerLength + ") does not match bytes read (" + ReadLength + ").");
            }
        }
 public void Read(TDSReader r)
 {
     if (r.TDSVersion == (UInt32)TDSVersions.Unknown)
     {
         throw new UnknownTDSVersionException("Column meta data needs to know the TDS version.");
     }
     ColumnCount = r.ReadUInt16();
     if (ColumnCount == 0xFFFF)
     {
         return;                          // no metadata - the client specified to return none
     }
     for (int i = 0; i < ColumnCount; i++)
     {
         TDSColumnMetaData cm = new TDSColumnMetaData();
         cm.Read(r);
         ColumnData.Add(cm);
     }
 }
        public void Read(TDSReader r)
        {
            uint   ReadLength = 4;
            uint   headerLength;
            ushort headerType;

            TotalLength = r.ReadUInt32();
            r.TokenStart((int)TotalLength - 4);    // TotalLength includes its own length (DWORD = 4 bytes)
            while (ReadLength < TotalLength)
            {
                headerLength = r.ReadUInt32();
                ReadLength  += headerLength;
                headerType   = r.ReadUInt16();
                switch (headerType)
                {
                case 1:
                {
                    notification = new TDSHeaderQueryNotification();
                    notification.Read(r, (int)headerLength);
                    break;
                }

                case 2:
                {
                    txd = new TDSHeaderTransactionDescriptor();
                    txd.Read(r);
                    break;
                }

                case 3:
                {
                    trace = new TDSHeaderTraceActivity();
                    trace.Read(r);
                    break;
                }
                }
            }
            r.TokenDone();
            if (TotalLength != ReadLength)
            {
                throw new InvalidTDSException("TDS HeaderAll TotalLength(" + TotalLength + ") does not equal ReadLength(" + ReadLength + ").");
            }
        }
        public string AlternateServer = null;   // server name to reroute the connection to

        public void Read(TDSReader r)
        {
            Length = r.ReadUInt16();
            r.TokenStart(Length);
            EnvChangeType = (TDSEnvChgTokens)r.ReadByte();
            if (EnvChangeType == TDSEnvChgTokens.PromoteTrans)
            {
                r.TokenDone();                                                // Length always 1 for this token type
            }
            switch (EnvChangeType)
            {
            case TDSEnvChgTokens.Database:                   //   1  Database name
            case TDSEnvChgTokens.Language:                   //   2  Language
            case TDSEnvChgTokens.CharSet:                    //   3  Character set                         - TDS 7.0
            case TDSEnvChgTokens.PacketSize:                 //   4  Packet Size
            case TDSEnvChgTokens.UnicodeSortLocale:          //   5  Unicode data sorting locale id        - TDS 7.0
            case TDSEnvChgTokens.UnicodeCompareFlags:        //   6  Unicode data sorting comparison flags - TDS 7.0
            case TDSEnvChgTokens.MirrorPartner:              //  13  Database mirroring partner
            case TDSEnvChgTokens.UserInfo:                   //  19  User instance
            {
                NewValue = r.ReadUnicodeString1();           // returns "" if length argument is zero
                OldValue = r.ReadUnicodeString1();
                break;
            }

            case TDSEnvChgTokens.Collation:                  //   7  SQL collation - generally 5 bytes
            case TDSEnvChgTokens.BeginTrans:                 //   8  Begin transaction          - old data is always 0x00 length
            case TDSEnvChgTokens.CommitTrans:                //   9  Commit transaction         - new data is always 0x00 length
            case TDSEnvChgTokens.RollbackTrans:              //  10  Rollback transaction       - new data is always 0x00 length
            case TDSEnvChgTokens.EnlistDTC:                  //  11  Enlist TDS transaction     - new data is always 0x00 length
            case TDSEnvChgTokens.DefectTrans:                //  12  Defect transaction         - old data is always 0x00 length
            case TDSEnvChgTokens.TransMgrAddress:            //  16  Transaction Manager Address- old data is always 0x00 length - unused token
            case TDSEnvChgTokens.TransEnded:                 //  17  Transaction Ended          - new data is always 0x00 length
            case TDSEnvChgTokens.ResetCompletedAck:          //  18  Reset achknowledgement     - new data and old data both 0x00 length
            {
                NewBytes = r.ReadBytes1();
                OldBytes = r.ReadBytes1();
                break;
            }

            case TDSEnvChgTokens.PromoteTrans:               //  15  Promote transaction        - new data length is 4 bytes, old data is always 0x00 length
            {
                NewBytes = r.ReadBytes4();
                r.ReadByte();             // no real old data, just a 1 byte 0-length indicator
                break;
            }

            case TDSEnvChgTokens.Routing:                    //  20  Routing                    - old data length is always 0x0000
            {
                // new value
                ushort RoutingDataLength = r.ReadUInt16();           // may be sent if ReadOnlyIntent is true in TDS 7.1 - 7.3; could be sent in 7.4 even if the flag is false
                if (RoutingDataLength > 0)
                {
                    Protocol         = r.ReadByte();
                    ProtocolProperty = r.ReadUInt16();
                    AlternateServer  = r.ReadUnicodeString2();
                }
                // old value
                r.ReadUInt16();
                break;
            }
            }
            if (EnvChangeType != TDSEnvChgTokens.PromoteTrans)
            {
                r.TokenDone();                                                 // Length for this token is always 1 even if there is more data; r.DoneToken(0 is called earlier for this token type
            }
        }
        public void Read(TDSReader r)
        {
            byte TDSVer = (byte)(r.TDSVersion & 0x000000FF);

            UserType = (TDSVer < 0x72) ? r.ReadUInt16() : r.ReadUInt32();
            Flags    = r.ReadUInt16();
            Type     = (TDSTokenColumnType)(r.ReadByte());
            switch (Type)
            {
            //
            // no need to read anything else for fixed-length types
            //
            case TDSTokenColumnType.Null:
            case TDSTokenColumnType.TinyInt:
            case TDSTokenColumnType.Bit:
            case TDSTokenColumnType.SmallInt:
            case TDSTokenColumnType.Int:
            case TDSTokenColumnType.SmallDateTime:
            case TDSTokenColumnType.Real:
            case TDSTokenColumnType.Money:
            case TDSTokenColumnType.DateTime:
            case TDSTokenColumnType.Float:
            case TDSTokenColumnType.SmallMoney:
            case TDSTokenColumnType.BigInt:
            {
                break;
            }

            //
            // data types that have a 1 byte length
            //
            case TDSTokenColumnType.GUID:
            case TDSTokenColumnType.VarBinary:
            case TDSTokenColumnType.IntN:
            case TDSTokenColumnType.VarChar:
            case TDSTokenColumnType.DateN:       // question about this type
            case TDSTokenColumnType.Binary:
            case TDSTokenColumnType.Char:
            case TDSTokenColumnType.BitN:
            case TDSTokenColumnType.FloatN:
            case TDSTokenColumnType.MoneyN:
            case TDSTokenColumnType.DateTimeN:
            {
                Length = r.ReadByte();
                break;
            }

            //
            // data types that have a 1 byte length and 1 byte scale
            //
            case TDSTokenColumnType.TimeN:
            case TDSTokenColumnType.DateTime2N:
            case TDSTokenColumnType.DateTimeOffsetN:
            {
                Length = r.ReadByte();
                Scale  = r.ReadByte();
                break;
            }

            //
            // data types that have a 1 byte length, 1 byte precision, and 1 byte scale
            //
            case TDSTokenColumnType.Decimal:
            case TDSTokenColumnType.Numeric:
            case TDSTokenColumnType.DecimalN:
            case TDSTokenColumnType.NumericN:
            {
                Length    = r.ReadByte();
                Precision = r.ReadByte();
                Scale     = r.ReadByte();
                break;
            }

            //
            // data types that have a 2 byte length
            //
            case TDSTokenColumnType.LongVarBinary:
            case TDSTokenColumnType.LongBinary:
            {
                Length = r.ReadUInt16();
                break;
            }

            //
            // data types that have a 2 byte length and an optional 5-byte collation
            //
            case TDSTokenColumnType.LongVarChar:
            case TDSTokenColumnType.LongChar:
            case TDSTokenColumnType.NVarChar:
            case TDSTokenColumnType.NChar:
            {
                Length = r.ReadUInt16();
                if (TDSVer >= 0x71)
                {
                    Collation = r.ReadBytes(5);
                }
                break;
            }

            //
            // data types that have a 4 byte length
            //
            case TDSTokenColumnType.Image:
            case TDSTokenColumnType.Variant:
            case TDSTokenColumnType.NText:
            {
                Length = r.ReadUInt32();
                break;
            }

            //
            // data types that have a 4 byte length and an optional 5-byte collation
            //
            case TDSTokenColumnType.Text:
            {
                Length = r.ReadUInt32();
                if (TDSVer >= 0x71)
                {
                    Collation = r.ReadBytes(5);
                }
                break;
            }

            //
            // CLR User-Defined Type
            //
            case TDSTokenColumnType.UDT:
            {
                Length       = r.ReadUInt16();
                DBName       = r.ReadUnicodeString1();
                SchemaName   = r.ReadUnicodeString1();
                TypeName     = r.ReadUnicodeString1();
                AssemblyName = r.ReadUnicodeString2();         // can be longer than 255 characters
                break;
            }

            //
            // XML
            //
            case TDSTokenColumnType.XML:
            {
                XmlSchemaPresent = r.ReadByte();
                if (XmlSchemaPresent == 1)
                {
                    DBName           = r.ReadUnicodeString1();
                    SchemaName       = r.ReadUnicodeString1();
                    SchemaCollection = r.ReadUnicodeString2();           // can be longer than 255 characters
                }
                break;
            }

            default:
            {
                throw new InvalidTDSException("Unknown TDS data type: " + (byte)(Type) + ".");
            }
            }
            ColumnName = r.ReadUnicodeString1();
        }
        byte[] Nonce          = null; // 32 bytes of data if FedAuth is non-zero

        public void Read(TDSReader r)
        {
            byte      OptionToken = 0;;
            int       DataOffset;
            int       DataLength;
            TDSReader offsetReader = null;

            OptionToken = r.ReadByte();

            while (OptionToken != (byte)TDSTokenType.DONEINPROC) // 255 or 0xFF
            {
                DataOffset   = r.ReadBigEndianUInt16();
                DataLength   = r.ReadBigEndianUInt16();
                offsetReader = r.OffsetReader(DataOffset);

                switch (OptionToken)
                {
                case 0:              // version
                {
                    if (DataLength > 0)
                    {
                        Version  = offsetReader.ReadUInt32();
                        SubBuild = offsetReader.ReadUInt16();
                    }
                    break;
                }

                case 1:             // encryption
                {
                    if (DataLength > 0)
                    {
                        Encryption = offsetReader.ReadByte();
                    }
                    if (Encryption > 3)
                    {
                        throw new InvalidTDSException("Invalid encryption option: " + Encryption);
                    }
                    break;
                }

                case 2:             // instanceValidity validity
                {
                    if (DataLength > 0)
                    {
                        InstanceValidity = offsetReader.ReadByte();
                    }
                    break;
                }

                case 3:             // thread ID
                {
                    if (DataLength > 0)
                    {
                        ThreadID = offsetReader.ReadUInt32();
                    }
                    break;
                }

                case 4:             // MARS
                {
                    if (DataLength > 0)
                    {
                        MarsData = offsetReader.ReadByte();
                    }
                    if (MarsData > 1)
                    {
                        throw new InvalidTDSException("Invalid MARS option: " + MarsData);
                    }
                    break;
                }

                case 5:            // Trace ID
                {
                    if (DataLength > 0)
                    {
                        TraceID = new Guid(offsetReader.ReadBytes(16));
                    }
                    break;
                }

                case 6:            // Federated Auth Required
                {
                    if (DataLength > 0)
                    {
                        FedAuth = offsetReader.ReadByte();
                    }
                    break;
                }

                case 7:            // NONCE Option - 32 bytes of encrypted data
                {
                    if (DataLength > 0)
                    {
                        Nonce = offsetReader.ReadBytes(32);
                    }
                    break;
                }
                }
            }
            r.DoneWithChildReaders();  // updates parent reader offset with child reader high offset - i.e.  causes the parent to jump past the referenced data
        }