Helper class that takes care of setting property value
        /// <summary>
        /// Deflate the token
        /// </summary>
        /// <param name="destination">Stream to deflate token to</param>
        public override void Deflate(Stream destination)
        {
            // Calculate total length by adding strings
            uint totalPacketLength = (uint)(FixedPacketLength
                                            + (uint)(string.IsNullOrEmpty(HostName) ? 0 : HostName.Length * 2)                     // HostName
                                            + (uint)(string.IsNullOrEmpty(UserID) ? 0 : UserID.Length * 2)                         // UserID
                                            + (uint)(string.IsNullOrEmpty(Password) ? 0 : Password.Length * 2)                     // Password
                                            + (uint)(string.IsNullOrEmpty(ApplicationName) ? 0 : ApplicationName.Length * 2)       // ApplicationName
                                            + (uint)(string.IsNullOrEmpty(ServerName) ? 0 : ServerName.Length * 2)                 // ServerName
                                            + (uint)(string.IsNullOrEmpty(LibraryName) ? 0 : LibraryName.Length * 2)               // LibraryName
                                            + (uint)(string.IsNullOrEmpty(Language) ? 0 : Language.Length * 2)                     // Language
                                            + (uint)(string.IsNullOrEmpty(Database) ? 0 : Database.Length * 2)                     // Database
                                            + (uint)(string.IsNullOrEmpty(AttachDatabaseFile) ? 0 : AttachDatabaseFile.Length * 2) // AttachDatabaseFile
                                            + (uint)(string.IsNullOrEmpty(ChangePassword) ? 0 : ChangePassword.Length * 2)         // ChangePassword
                                            + (uint)(SSPI == null ? 0 : SSPI.Length)                                               // SSPI
                                            + 0);                                                                                  // Feature extension

            MemoryStream featureExtension = null;

            // Check if we have a feature extension
            if (FeatureExt != null)
            {
                // Allocate feature extension block
                featureExtension = new MemoryStream();

                // Serialize feature extension
                FeatureExt.Deflate(featureExtension);

                // Update total lentgh
                totalPacketLength += (uint)(sizeof(uint) /* Offset of feature extension data */ + featureExtension.Length /* feature extension itself*/);
            }

            // Write packet length
            TDSUtilities.WriteUInt(destination, totalPacketLength);

            // Compile TDS version
            uint tdsVersion = Convert.ToUInt32(string.Format("{0:X}", Math.Max(TDSVersion.Major, 0)) + string.Format("{0:X}", Math.Max(TDSVersion.Minor, 0)) + string.Format("{0:X2}", Math.Max(TDSVersion.Build, 0)) + string.Format("{0:X4}", Math.Max(TDSVersion.Revision, 0)), 16);

            // Write TDS version
            TDSUtilities.WriteUInt(destination, tdsVersion);

            // Write packet length
            TDSUtilities.WriteUInt(destination, PacketSize);

            // Write client program version
            TDSUtilities.WriteUInt(destination, ClientProgramVersion);

            // Write client program identifier
            TDSUtilities.WriteUInt(destination, ClientPID);

            // Write connection identifier
            TDSUtilities.WriteUInt(destination, ConnectionID);

            // Write the first optional flags
            destination.WriteByte(OptionalFlags1.ToByte());

            // Write the second optional flags
            destination.WriteByte(OptionalFlags2.ToByte());

            // Instantiate type flags
            destination.WriteByte(TypeFlags.ToByte());

            // Write the third optional flags
            destination.WriteByte(OptionalFlags3.ToByte());

            // Write client time zone
            TDSUtilities.WriteInt(destination, ClientTimeZone);

            // Write client locale identifier
            TDSUtilities.WriteUInt(destination, ClientLCID);

            // Prepare a collection of property values that will be set later
            IList <TDSLogin7TokenOffsetProperty> variableProperties = new List <TDSLogin7TokenOffsetProperty>();

            // Write client host name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("HostName"), FixedPacketLength, (ushort)(string.IsNullOrEmpty(HostName) ? 0 : HostName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write user name and password
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("UserID"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(UserID) ? 0 : UserID.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Password"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Password) ? 0 : Password.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write application name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ApplicationName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ApplicationName) ? 0 : ApplicationName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write server name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ServerName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ServerName) ? 0 : ServerName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Check if we have a feature extension block
            if (FeatureExt != null)
            {
                // Write the offset of the feature extension offset (pointer to pointer)
                variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("FeatureExt"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), sizeof(uint) / 2, true)); // Should be 4 bytes, devided by 2 because the next guy multiplies by 2
                TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
                TDSUtilities.WriteUShort(destination, (ushort)(variableProperties.Last().Length * 2));                                                                                                                      // Compensate for division by 2 above
            }
            else
            {
                // Skip unused
                TDSUtilities.WriteUShort(destination, 0);
                TDSUtilities.WriteUShort(destination, 0);
            }

            // Write client library name
            // We do not need to account for skipped unused bytes here because they're already accounted in fixedPacketLength
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("LibraryName"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(LibraryName) ? 0 : LibraryName.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write language
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Language"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Language) ? 0 : Language.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write database
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Database"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(Database) ? 0 : Database.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Check if client is defined
            if (ClientID == null)
            {
                // Allocate empty identifier
                ClientID = new byte[6];
            }

            // Write unique client identifier
            destination.Write(ClientID, 0, 6);

            // Write SSPI
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("SSPI"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(SSPI == null ? 0 : SSPI.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write database file to be attached. NOTE, "variableProperties.Last().Length" without " * 2" because the preceeding buffer isn't string
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("AttachDatabaseFile"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length), (ushort)(string.IsNullOrEmpty(AttachDatabaseFile) ? 0 : AttachDatabaseFile.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Write password change
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ChangePassword"), (ushort)(variableProperties.Last().Position + variableProperties.Last().Length * 2), (ushort)(string.IsNullOrEmpty(ChangePassword) ? 0 : ChangePassword.Length)));
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Position);
            TDSUtilities.WriteUShort(destination, (ushort)variableProperties.Last().Length);

            // Skip long SSPI
            TDSUtilities.WriteUInt(destination, 0);

            // We will be changing collection as we go and serialize everything. As such we can't use foreach and iterator.
            int iCurrentProperty = 0;

            // Iterate through the collection
            while (iCurrentProperty < variableProperties.Count)
            {
                // Get current property by index
                TDSLogin7TokenOffsetProperty property = variableProperties[iCurrentProperty];

                // Check if length is positive
                if (property.Length == 0)
                {
                    // Move to the next property
                    iCurrentProperty++;
                    continue;
                }

                // Check special properties
                if (property.Property.Name == "Password" || property.Property.Name == "ChangePassword")
                {
                    // Write encrypted string value
                    TDSUtilities.WritePasswordString(destination, (string)property.Property.GetValue(this, null));
                }
                else if (property.Property.Name == "FeatureExt")
                {
                    // Check if we are to serialize the offset or the actual data
                    if (property.IsOffsetOffset)
                    {
                        // Property will be written at the offset immediately following all variable length data
                        property.Position = variableProperties.Last().Position + variableProperties.Last().Length;

                        // Write the position at which we'll be serializing the feature extension block
                        TDSUtilities.WriteUInt(destination, property.Position);

                        // Order strings in ascending order by offset
                        variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

                        // Compensate increment to the next position in order to stay on the same
                        iCurrentProperty--;

                        // No longer offset, actual data is going to follow
                        property.IsOffsetOffset = false;
                    }
                    else
                    {
                        // Transfer deflated feature extension into the login stream
                        featureExtension.WriteTo(destination);
                    }
                }
                else if (property.Property.Name == "SSPI")
                {
                    // Write SSPI
                    destination.Write(SSPI, 0, SSPI.Length);
                }
                else
                {
                    // Write the string value
                    TDSUtilities.WriteString(destination, (string)property.Property.GetValue(this, null));
                }

                // Move to the next property
                iCurrentProperty++;
            }
        }
        /// <summary>
        /// Inflate the token
        /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream
        /// </summary>
        /// <param name="source">Stream to inflate the token from</param>
        /// <returns>TRUE if inflation is complete</returns>
        public override bool Inflate(Stream source)
        {
            // Read packet length
            uint length = TDSUtilities.ReadUInt(source);

            // Read TDS version
            string tdsVersion = string.Format("{0:X}", TDSUtilities.ReadUInt(source));

            // Consturct TDS version
            TDSVersion = new Version(int.Parse(tdsVersion.Substring(0, 1)), int.Parse(tdsVersion.Substring(1, 1)), Convert.ToInt32(tdsVersion.Substring(2, 2), 16), Convert.ToInt32(tdsVersion.Substring(4, 4), 16));

            // Read packet length
            PacketSize = TDSUtilities.ReadUInt(source);

            // Read client program version
            ClientProgramVersion = TDSUtilities.ReadUInt(source);

            // Read client program identifier
            ClientPID = TDSUtilities.ReadUInt(source);

            // Read connection identifier
            ConnectionID = TDSUtilities.ReadUInt(source);

            // Instantiate the first optional flags
            OptionalFlags1 = new TDSLogin7TokenOptionalFlags1((byte)source.ReadByte());

            // Instantiate the second optional flags
            OptionalFlags2 = new TDSLogin7TokenOptionalFlags2((byte)source.ReadByte());

            // Instantiate type flags
            TypeFlags = new TDSLogin7TokenTypeFlags((byte)source.ReadByte());

            // Instantiate the third optional flags
            OptionalFlags3 = new TDSLogin7TokenOptionalFlags3((byte)source.ReadByte());

            // Read client time zone
            ClientTimeZone = TDSUtilities.ReadInt(source);

            // Read client locale identifier
            ClientLCID = TDSUtilities.ReadUInt(source);

            // Prepare a collection of property values that will be set later
            IList <TDSLogin7TokenOffsetProperty> variableProperties = new List <TDSLogin7TokenOffsetProperty>();

            // Read client host name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("HostName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read user name and password
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("UserID"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Password"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read application name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ApplicationName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read server name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ServerName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Check if extension is used
            if (OptionalFlags3.ExtensionFlag)
            {
                // Read Feature extension. Note that this is just an offset of the value, not the value itself
                variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("FeatureExt"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source), true));
            }
            else
            {
                // Skip unused
                TDSUtilities.ReadUShort(source);
                TDSUtilities.ReadUShort(source);
            }

            // Read client library name
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("LibraryName"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read language
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Language"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read database
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("Database"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            ClientID = new byte[6];

            // Read unique client identifier
            source.Read(ClientID, 0, ClientID.Length);

            // Read SSPI blob
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("SSPI"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read database file to be attached
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("AttachDatabaseFile"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read password change
            variableProperties.Add(new TDSLogin7TokenOffsetProperty(GetType().GetProperty("ChangePassword"), TDSUtilities.ReadUShort(source), TDSUtilities.ReadUShort(source)));

            // Read long SSPI
            uint sspiLength = TDSUtilities.ReadUInt(source);

            // At this point we surpassed the fixed packet length
            long inflationOffset = FixedPacketLength;

            // Order strings in ascending order by offset
            // For the most cases this should not change the order of the options in the stream, but just in case
            variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

            // We can't use "foreach" because FeatureExt processing changes the collection hence we can only go index-based way
            int iCurrentProperty = 0;

            // Iterate over each property
            while (iCurrentProperty < variableProperties.Count)
            {
                // Get the property at the indexed position
                TDSLogin7TokenOffsetProperty property = variableProperties[iCurrentProperty];

                // Check if length is positive
                if (property.Length == 0)
                {
                    // Move to the next propety
                    iCurrentProperty++;
                    continue;
                }

                // Ensure that current offset points to the option
                while (inflationOffset < property.Position)
                {
                    // Read the stream
                    source.ReadByte();

                    // Advance position
                    inflationOffset++;
                }

                // Check special properties
                if (property.Property.Name == "Password" || property.Property.Name == "ChangePassword")
                {
                    // Read passwod string
                    property.Property.SetValue(this, TDSUtilities.ReadPasswordString(source, (ushort)(property.Length * 2)), null);

                    // Advance the position
                    inflationOffset += (property.Length * 2);
                }
                else if (property.Property.Name == "SSPI")
                {
                    // If cbSSPI < USHRT_MAX, then this length MUST be used for SSPI and cbSSPILong MUST be ignored.
                    // If cbSSPI == USHRT_MAX, then cbSSPILong MUST be checked.
                    if (property.Length == ushort.MaxValue)
                    {
                        // If cbSSPILong > 0, then that value MUST be used. If cbSSPILong ==0, then cbSSPI (USHRT_MAX) MUST be used.
                        if (sspiLength > 0)
                        {
                            // We don't know how to handle SSPI packets that exceed TDS packet size
                            throw new NotSupportedException("Long SSPI blobs are not supported yet");
                        }
                    }

                    // Use short length instead
                    sspiLength = property.Length;

                    // Allocate buffer for SSPI data
                    SSPI = new byte[sspiLength];

                    // Read SSPI blob
                    source.Read(SSPI, 0, SSPI.Length);

                    // Advance the position
                    inflationOffset += sspiLength;
                }
                else if (property.Property.Name == "FeatureExt")
                {
                    // Check if this is the property or a pointer to the property
                    if (property.IsOffsetOffset)
                    {
                        // Read the actual offset of the feature extension
                        property.Position = TDSUtilities.ReadUInt(source);

                        // Mark that now we have actual value
                        property.IsOffsetOffset = false;

                        // Advance the position
                        inflationOffset += sizeof(uint);

                        // Re-order the collection
                        variableProperties = variableProperties.OrderBy(p => p.Position).ToList();

                        // Subtract position to stay on the same spot for subsequent property
                        iCurrentProperty--;
                    }
                    else
                    {
                        // Create a list of features.
                        FeatureExt = new TDSLogin7FeatureOptionsToken();

                        // Inflate feature extension
                        FeatureExt.Inflate(source);

                        // Advance position by the size of the inflated token
                        inflationOffset += FeatureExt.InflationSize;
                    }
                }
                else
                {
                    // Read the string and assign it to the property of this instance
                    property.Property.SetValue(this, TDSUtilities.ReadString(source, (ushort)(property.Length * 2)), null);

                    // Advance the position
                    inflationOffset += (property.Length * 2);
                }

                // Advance to the next property
                iCurrentProperty++;
            }

            return(true);
        }