/// <summary> /// Deflate the token /// </summary> /// <param name="destination">Stream to deflate token to</param> public override void Deflate(Stream destination) { // Write token identifier destination.WriteByte((byte)TDSTokenType.ReturnStatus); // Write value TDSUtilities.WriteInt(destination, 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++; } }