/// <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 return value Value = TDSUtilities.ReadInt(source); return(true); }
/// <summary> /// Read the raw data but don't interpret it /// </summary> protected byte[] InflateValue(Stream source) { // Read the next byte to check if length is DWORD int length = (int)source.ReadByte(); // Update inflation size InflationSize += sizeof(byte); // Check if (length == 0xFF) { // Length is long length = TDSUtilities.ReadInt(source); // Update inflation size InflationSize += sizeof(int); } // Allocate a container byte[] value = new byte[length]; // Read all bytes source.Read(value, 0, value.Length); // Update inflation size InflationSize += (uint)length; return(value); }
public static object InflateColumnData(Stream source, TDSDataType column, Object dataTypeSpecific) { // Dispatch further reading based on the type switch (column) { case TDSDataType.Null: { // No data associated with it return(null); } case TDSDataType.DateTime: { int daypart = TDSUtilities.ReadInt(source); uint timepart = TDSUtilities.ReadUInt(source); return(null); } case TDSDataType.DateTime2N: { var length = (byte)source.ReadByte(); var rawDate = new byte[length]; source.Read(rawDate, 0, length); uint secondIncrements = 0; for (int i = 0; i < length - 3; i++) { secondIncrements += (uint)(rawDate[i] << (8 * i)); } var days = (uint)rawDate[length - 3] + (uint)(rawDate[length - 2] << 8) + (uint)(rawDate[length - 1] << 16); var date = new DateTime(1, 1, 1).AddDays(days).AddSeconds(secondIncrements * Math.Pow(10, -1 * 5)); return(date); } case TDSDataType.Bit: case TDSDataType.Int1: { // Bit, 1 byte data representation return((byte)source.ReadByte()); } case TDSDataType.Int2: { // SmallInt, 2 byte data representation return(unchecked ((short)TDSUtilities.ReadUShort(source))); } case TDSDataType.Int4: { // Int, 4 byte data representation return(unchecked ((int)TDSUtilities.ReadUInt(source))); } case TDSDataType.Float8: { // Float (8 byte data representation) return(BitConverter.ToDouble(BitConverter.GetBytes(TDSUtilities.ReadULong(source)), 0)); } case TDSDataType.Int8: { // BigInt (8 byte data representation) return(unchecked ((long)TDSUtilities.ReadULong(source))); } case TDSDataType.BitN: { // Read length byte length = (byte)source.ReadByte(); // Check if null if (length == 0) { // No data return(null); } // Bit, 1 byte data representation return((byte)source.ReadByte()); } case TDSDataType.IntN: { // Read length byte length = (byte)source.ReadByte(); // Check integer length switch (length) { case 0: { // No data return(null); } case 1: { // Bit data return((byte)source.ReadByte()); } case 2: { // Short data return(unchecked ((short)TDSUtilities.ReadUShort(source))); } case 4: { // Integer data return(unchecked ((int)TDSUtilities.ReadUInt(source))); } case 8: { // Integer data return(unchecked ((long)TDSUtilities.ReadULong(source))); } default: { // We don't know how to inflate this integer throw new InvalidDataException(string.Format("Unable to inflate integer of {0} bytes", length)); } } } case TDSDataType.NumericN: { // Read length byte length = (byte)source.ReadByte(); // Check if null if (length == 0) { // No data return(null); } // Allocate value container byte[] guidBytes = new byte[length]; // Read value source.Read(guidBytes, 0, guidBytes.Length); // Instantiate type return(guidBytes); } case TDSDataType.Guid: { // Read the length byte length = (byte)source.ReadByte(); // Check if we have any data if (length == 0x0000) { // No data return(null); } // Allocate value container byte[] guidBytes = new byte[length]; // Read value source.Read(guidBytes, 0, guidBytes.Length); // Convert to type return(new Guid(guidBytes)); } case TDSDataType.BigVarChar: case TDSDataType.BigChar: { // Read length ushort length = TDSUtilities.ReadUShort(source); // Check if we have any data if (length == 0xFFFF) { // No data return(null); } // Allocate value container byte[] textBytes = new byte[length]; // Read value source.Read(textBytes, 0, textBytes.Length); // Convert to type return(Encoding.ASCII.GetString(textBytes)); } case TDSDataType.NVarChar: { // Check if MAX type if ((dataTypeSpecific as TDSShilohVarCharColumnSpecific).Length == 0xFFFF) { // Read the length of partialy length-prefixed type ulong length = TDSUtilities.ReadULong(source); // Check the value if (length == 0xFFFFFFFFFFFFFFFF) { // There's no data return(null); } else if (length == 0xFFFFFFFFFFFFFFFE) { throw new NotImplementedException("UNKNOWN_PLP_LEN is not implemented yet"); } else { // Allocate a memory stream MemoryStream chunks = new MemoryStream(); // Size of the last chunk uint chunkLength = 0; // Iterate until we read the whole data do { // Read the length of the chunk chunkLength = TDSUtilities.ReadUInt(source); // Allocate chunk container byte[] chunk = new byte[chunkLength]; // Read value source.Read(chunk, 0, chunk.Length); // Append into the stream chunks.Write(chunk, 0, chunk.Length); }while (chunkLength > 0); // Convert to byte array byte[] byteString = chunks.ToArray(); // Serialize the data into the string return(Encoding.Unicode.GetString(byteString, 0, byteString.Length)); } } else { // Read length ushort length = TDSUtilities.ReadUShort(source); // Check if we have any data if (length == 0xFFFF) { // No data return(null); } // Read the whole string at once return(TDSUtilities.ReadString(source, (ushort)length)); } } case TDSDataType.BigVarBinary: { byte[] bytes = null; // Check if MAX type if ((ushort)dataTypeSpecific == 0xFFFF) { // Read the length of partialy length-prefixed type ulong length = TDSUtilities.ReadULong(source); // Check the value if (length == 0xFFFFFFFFFFFFFFFF) { // There's no data return(null); } else if (length == 0xFFFFFFFFFFFFFFFE) { throw new NotImplementedException("UNKNOWN_PLP_LEN is not implemented yet"); } else { // Allocate a memory stream MemoryStream chunks = new MemoryStream(); // Size of the last chunk uint chunkLength = 0; // Iterate until we read the whole data do { // Read the length of the chunk chunkLength = TDSUtilities.ReadUInt(source); // Allocate chunk container byte[] chunk = new byte[chunkLength]; // Read value source.Read(chunk, 0, chunk.Length); // Append into the stream chunks.Write(chunk, 0, chunk.Length); }while (chunkLength > 0); // Serialize to byte array bytes = chunks.ToArray(); } } else { // Read length ushort length = TDSUtilities.ReadUShort(source); // Check if we have any data if (length == 0xFFFF) { // No data return(null); } // Allocate value container bytes = new byte[length]; // Read value source.Read(bytes, 0, bytes.Length); } // Convert to type return(bytes); } case TDSDataType.BigBinary: { // Read length ushort length = TDSUtilities.ReadUShort(source); // Check if we have any data if (length == 0xFFFF) { // No data return(null); } // Allocate value container byte[] bytes = new byte[length]; // Read value source.Read(bytes, 0, bytes.Length); // Convert to type return(bytes); } default: { // We don't know this type throw new NotImplementedException(string.Format("Unrecognized data type {0} for inflation", column)); } } }
/// <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); }