290 lines
7.5 KiB
C#
Raw Normal View History

//
// Mono.Data.Tds.Protocol.Tds42.cs
//
// Author:
// Tim Coleman (tim@timcoleman.com)
//
// Copyright (C) 2002 Tim Coleman
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security;
namespace Mono.Data.Tds.Protocol {
public sealed class Tds42 : Tds
{
#region Fields
public static readonly TdsVersion Version = TdsVersion.tds42;
#endregion // Fields
#region Constructors
public Tds42 (string server, int port)
: this (server, port, 512, 15)
{
}
public Tds42 (string server, int port, int packetSize, int timeout)
: base (server, port, packetSize, timeout, Version)
{
}
#endregion // Constructors
#region Methods
public override bool Connect (TdsConnectionParameters connectionParameters)
{
if (IsConnected)
throw new InvalidOperationException ("The connection is already open.");
SetCharset (connectionParameters.Charset);
SetLanguage (connectionParameters.Language);
byte pad = (byte) 0;
byte[] empty = new byte[0];
Comm.StartPacket (TdsPacketType.Logon);
// hostname (offset 0)
byte[] tmp = Comm.Append (connectionParameters.Hostname, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// username (offset 31 0x1f)
tmp = Comm.Append (connectionParameters.User, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// password (offset 62 0x3e)
tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// hostproc (offset 93 0x5d)
Comm.Append ("00000116", 8, pad);
// unused (offset 109 0x6d)
Comm.Append (empty, (30-14), pad);
// apptype
Comm.Append ((byte) 0x0);
Comm.Append ((byte) 0xa0);
Comm.Append ((byte) 0x24);
Comm.Append ((byte) 0xcc);
Comm.Append ((byte) 0x50);
Comm.Append ((byte) 0x12);
// hostproc length
Comm.Append ((byte) 8);
// Byte order of 2 byte ints
// 2 = <MSB, LSB>, 3 = <LSB, MSB>
Comm.Append ((byte) 3);
// Byte order of 4 byte ints
// 0 = <MSB, LSB>, 1 = <LSB, MSB>
Comm.Append ((byte) 1);
// Character representation
// (6 = ASCII, 7 = EBCDIC)
Comm.Append ((byte) 6);
// Eight byte floating point representation
// 4 = IEEE <MSB, ..., LSB>
// 5 = VAX 'D'
// 10 = IEEE <LSB, ..., MSB>
// 11 = ND5000
Comm.Append ((byte) 10);
// Eight byte date format
// 8 = <MSB, ..., LSB>
Comm.Append ((byte) 9);
// notify of use db
Comm.Append ((byte) 1);
// disallow dump/load and bulk insert
Comm.Append ((byte) 1);
// sql interface type
Comm.Append ((byte) 0);
// type of network connection
Comm.Append ((byte) 0);
// spare [7]
Comm.Append (empty, 7, pad);
// appname
tmp = Comm.Append (connectionParameters.ApplicationName, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// server name
tmp = Comm.Append (DataSource, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// remote passwords
Comm.Append (empty, 2, pad);
tmp = Comm.Append (GetPlainPassword(connectionParameters.Password), 253, pad);
Comm.Append ((byte) (tmp.Length < 253 ? tmp.Length + 2 : 253 + 2));
// tds version
Comm.Append ((byte) (((byte) Version) / 10));
Comm.Append ((byte) (((byte) Version) % 10));
Comm.Append ((byte) 0);
Comm.Append ((byte) 0);
// prog name
tmp = Comm.Append (connectionParameters.ProgName, 10, pad);
Comm.Append ((byte) (tmp.Length < 10 ? tmp.Length : 10));
// prog version
Comm.Append ((byte) 6);
// Tell the server we can handle SQLServer version 6
Comm.Append ((byte) 0);
// Send zero to tell the server we can't handle any other version
Comm.Append ((byte) 0);
Comm.Append ((byte) 0);
// auto convert short
Comm.Append ((byte) 0);
// type of flt4
Comm.Append ((byte) 0x0d);
// type of date4
Comm.Append ((byte) 0x11);
// language
tmp = Comm.Append (Language, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// notify on lang change
Comm.Append ((byte) 1);
// security label hierarchy
Comm.Append ((short) 0);
// security components
Comm.Append (empty, 8, pad);
// security spare
Comm.Append ((short) 0);
// security login role
Comm.Append ((byte) 0);
// charset
tmp = Comm.Append (Charset, 30, pad);
Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
// notify on charset change
Comm.Append ((byte) 1);
// length of tds packets
tmp = Comm.Append (PacketSize.ToString (), 6, pad);
Comm.Append ((byte) 3);
// pad out to a longword
Comm.Append (empty, 8, pad);
Comm.SendPacket ();
MoreResults = true;
SkipToEnd ();
return IsConnected;
}
protected override void ProcessColumnInfo ()
{
byte precision;
byte scale;
int totalLength = Comm.GetTdsShort ();
int bytesRead = 0;
while (bytesRead < totalLength) {
scale = 0;
precision = 0;
int bufLength = -1;
byte[] flagData = new byte[4];
for (int i = 0; i < 4; i += 1) {
flagData[i] = Comm.GetByte ();
bytesRead += 1;
}
bool nullable = (flagData[2] & 0x01) > 0;
//bool caseSensitive = (flagData[2] & 0x02) > 0;
bool writable = (flagData[2] & 0x0c) > 0;
//bool autoIncrement = (flagData[2] & 0x10) > 0;
string tableName = String.Empty;
TdsColumnType columnType = (TdsColumnType) Comm.GetByte ();
bytesRead += 1;
if (columnType == TdsColumnType.Text || columnType == TdsColumnType.Image) {
Comm.Skip (4);
bytesRead += 4;
int tableNameLength = Comm.GetTdsShort ();
bytesRead += 2;
tableName = Comm.GetString (tableNameLength);
bytesRead += tableNameLength;
bufLength = 2 << 31 - 1;
}
else if (columnType == TdsColumnType.Decimal || columnType == TdsColumnType.Numeric) {
bufLength = Comm.GetByte ();
bytesRead += 1;
precision = Comm.GetByte ();
bytesRead += 1;
scale = Comm.GetByte ();
bytesRead += 1;
}
else if (IsFixedSizeColumn (columnType))
bufLength = LookupBufferSize (columnType);
else {
bufLength = (int) Comm.GetByte () & 0xff;
bytesRead += 1;
}
TdsDataColumn col = new TdsDataColumn ();
int index = Columns.Add (col);
col.ColumnType = columnType;
col.ColumnSize = bufLength;
col.ColumnName = ColumnNames[index] as string;
col.NumericPrecision = precision;
col.NumericScale = scale;
col.IsReadOnly = !writable;
col.BaseTableName = tableName;
col.AllowDBNull = nullable;
}
}
#endregion // Methods
}
}