private void SendPreLoginHandshake(byte[] instanceName, bool encrypt)
{
// PreLoginHandshake buffer consists of:
// 1) Standard header, with type = MT_PRELOGIN
// 2) Consecutive 5 bytes for each option, (1 byte length, 2 byte offset, 2 byte payload length)
// 3) Consecutive data blocks for each option
// NOTE: packet data needs to be big endian - not the standard little endian used by
// the rest of the parser.
_physicalStateObj._outputMessageType = TdsEnums.MT_PRELOGIN;
// Initialize option offset into payload buffer
// 5 bytes for each option (1 byte length, 2 byte offset, 2 byte payload length)
int offset = (int)PreLoginOptions.NUMOPT * 5 + 1;
byte[] payload = new byte[(int)PreLoginOptions.NUMOPT * 5 + TdsEnums.MAX_PRELOGIN_PAYLOAD_LENGTH];
int payloadLength = 0;
for (int option = (int)PreLoginOptions.VERSION; option < (int)PreLoginOptions.NUMOPT; option++)
{
int optionDataSize = 0;
// Fill in the option
_physicalStateObj.WriteByte((byte)option);
// Fill in the offset of the option data
_physicalStateObj.WriteByte((byte)((offset & 0xff00) >> 8)); // send upper order byte
_physicalStateObj.WriteByte((byte)(offset & 0x00ff)); // send lower order byte
switch (option)
{
case (int)PreLoginOptions.VERSION:
Version systemDataVersion = ADP.GetAssemblyVersion();
// Major and minor
payload[payloadLength++] = (byte)(systemDataVersion.Major & 0xff);
payload[payloadLength++] = (byte)(systemDataVersion.Minor & 0xff);
// Build (Big Endian)
payload[payloadLength++] = (byte)((systemDataVersion.Build & 0xff00) >> 8);
payload[payloadLength++] = (byte)(systemDataVersion.Build & 0xff);
// Sub-build (Little Endian)
payload[payloadLength++] = (byte)(systemDataVersion.Revision & 0xff);
payload[payloadLength++] = (byte)((systemDataVersion.Revision & 0xff00) >> 8);
offset += 6;
optionDataSize = 6;
break;
case (int)PreLoginOptions.ENCRYPT:
if (_encryptionOption == EncryptionOptions.NOT_SUP)
{
// If OS doesn't support encryption, inform server not supported.
payload[payloadLength] = (byte)EncryptionOptions.NOT_SUP;
}
else
{
// Else, inform server of user request.
if (encrypt)
{
payload[payloadLength] = (byte)EncryptionOptions.ON;
_encryptionOption = EncryptionOptions.ON;
}
else
{
payload[payloadLength] = (byte)EncryptionOptions.OFF;
_encryptionOption = EncryptionOptions.OFF;
}
}
payloadLength += 1;
offset += 1;
optionDataSize = 1;
break;
case (int)PreLoginOptions.INSTANCE:
int i = 0;
while (instanceName[i] != 0)
{
payload[payloadLength] = instanceName[i];
payloadLength++;
i++;
}
payload[payloadLength] = 0; // null terminate
payloadLength++;
i++;
offset += i;
optionDataSize = i;
break;
case (int)PreLoginOptions.THREADID:
Int32 threadID = TdsParserStaticMethods.GetCurrentThreadIdForTdsLoginOnly();
payload[payloadLength++] = (byte)((0xff000000 & threadID) >> 24);
payload[payloadLength++] = (byte)((0x00ff0000 & threadID) >> 16);
payload[payloadLength++] = (byte)((0x0000ff00 & threadID) >> 8);
payload[payloadLength++] = (byte)(0x000000ff & threadID);
offset += 4;
optionDataSize = 4;
break;
case (int)PreLoginOptions.MARS:
payload[payloadLength++] = (byte)(_fMARS ? 1 : 0);
offset += 1;
optionDataSize += 1;
break;
case (int)PreLoginOptions.TRACEID:
byte[] connectionIdBytes = _connHandler._clientConnectionId.ToByteArray();
Debug.Assert(GUID_SIZE == connectionIdBytes.Length);
Buffer.BlockCopy(connectionIdBytes, 0, payload, payloadLength, GUID_SIZE);
payloadLength += GUID_SIZE;
offset += GUID_SIZE;
optionDataSize = GUID_SIZE;
ActivityCorrelator.ActivityId actId = ActivityCorrelator.Next();
connectionIdBytes = actId.Id.ToByteArray();
Buffer.BlockCopy(connectionIdBytes, 0, payload, payloadLength, GUID_SIZE);
payloadLength += GUID_SIZE;
payload[payloadLength++] = (byte)(0x000000ff & actId.Sequence);
payload[payloadLength++] = (byte)((0x0000ff00 & actId.Sequence) >> 8);
payload[payloadLength++] = (byte)((0x00ff0000 & actId.Sequence) >> 16);
payload[payloadLength++] = (byte)((0xff000000 & actId.Sequence) >> 24);
int actIdSize = GUID_SIZE + sizeof(UInt32);
offset += actIdSize;
optionDataSize += actIdSize;
break;
default:
Debug.Assert(false, "UNKNOWN option in SendPreLoginHandshake");
break;
}
// Write data length
_physicalStateObj.WriteByte((byte)((optionDataSize & 0xff00) >> 8));
_physicalStateObj.WriteByte((byte)(optionDataSize & 0x00ff));
}
// Write out last option - to let server know the second part of packet completed
_physicalStateObj.WriteByte((byte)PreLoginOptions.LASTOPT);
// Write out payload
_physicalStateObj.WriteByteArray(payload, payloadLength, 0);
// Flush packet
_physicalStateObj.WritePacket(TdsEnums.HARDFLUSH);
}