| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Transactions
- {
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.IO;
- using System.Net;
- using System.Runtime;
- using System.Security.Permissions;
- using System.Text;
- using Microsoft.Transactions.Wsat.Protocol;
- using Microsoft.Transactions.Wsat.Recovery;
- class WhereaboutsReader
- {
- string hostName;
- ProtocolInformationReader protocolInfo;
- // Whereabouts internals
- static Guid GuidWhereaboutsInfo = new Guid("{2adb4462-bd41-11d0-b12e-00c04fc2f3ef}");
- const long STmToTmProtocolSize = 4 + 4;
- enum TmProtocol
- {
- TmProtocolNone = 0,
- TmProtocolTip = 1,
- TmProtocolMsdtcV1 = 2,
- TmProtocolMsdtcV2 = 3, // unicode host names in nameobject blobs etc
- TmProtocolExtended = 4 // other stuff (e.g., WS-AT)
- }
- public WhereaboutsReader(byte[] whereabouts)
- {
- MemoryStream mem = new MemoryStream(whereabouts,
- 0,
- whereabouts.Length,
- false,
- true); // Enable calls to GetBuffer()
- DeserializeWhereabouts(mem);
- }
- public string HostName
- {
- get { return this.hostName; }
- }
- public ProtocolInformationReader ProtocolInformation
- {
- get { return this.protocolInfo; }
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationException and SerializationUtils are safe.")]
- void DeserializeWhereabouts(MemoryStream mem)
- {
- // guidSignature
- Guid signature = SerializationUtils.ReadGuid(mem);
- if (signature != GuidWhereaboutsInfo)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsSignatureMissing)));
- }
- // cTmToTmProtocols
- uint cTmToTmProtocols = SerializationUtils.ReadUInt(mem);
- // Make sure that cTmToTmProtocols is at least plausible
- if (cTmToTmProtocols * STmToTmProtocolSize > mem.Length - mem.Position)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsImplausibleProtocolCount)));
- }
- // Loop through each protocol
- for (uint i = 0; i < cTmToTmProtocols; i++)
- {
- DeserializeWhereaboutsProtocol(mem);
- }
- // Require a host name
- if (string.IsNullOrEmpty(this.hostName))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsNoHostName)));
- }
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationUtils are safe.")]
- void DeserializeWhereaboutsProtocol(MemoryStream mem)
- {
- // tmprotDescribed
- TmProtocol tmprotDescribed = (TmProtocol)SerializationUtils.ReadInt(mem);
- // cbTmProtocolData
- uint cbTmProtocolData = SerializationUtils.ReadUInt(mem);
- switch (tmprotDescribed)
- {
- case TmProtocol.TmProtocolMsdtcV2:
- ReadMsdtcV2Protocol(mem, cbTmProtocolData);
- break;
- case TmProtocol.TmProtocolExtended:
- ReadExtendedProtocol(mem, cbTmProtocolData);
- break;
- default:
- // We don't care about this protocol
- SerializationUtils.IncrementPosition(mem, cbTmProtocolData);
- break;
- }
- // Align the cursor to a 4-byte boundary
- SerializationUtils.AlignPosition(mem, 4);
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationException and SerializationUtils are safe.")]
- void ReadMsdtcV2Protocol(MemoryStream mem, uint cbTmProtocolData)
- {
- const int MaxComputerName = 15;
- //
- // The host name is encoded in unicode format
- // It is followed by a null-terminating unicode character,
- // plus some padding to align on 4
- //
- // Reject host names of disproportionate size
- if (cbTmProtocolData > (MaxComputerName + 1) * 2)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsImplausibleHostNameByteCount)));
- }
- byte[] chars = SerializationUtils.ReadBytes(mem, (int)cbTmProtocolData);
- // Count the bytes until the first null terminating character
- int cbString = 0;
- while (cbString < cbTmProtocolData - 1 &&
- (chars[cbString] != 0 || chars[cbString + 1] != 0))
- {
- cbString += 2;
- }
- if (cbString == 0)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsInvalidHostName)));
- }
- try
- {
- this.hostName = Encoding.Unicode.GetString(chars, 0, cbString);
- }
- catch (ArgumentException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new SerializationException(SR.GetString(SR.WhereaboutsInvalidHostName), e));
- }
- }
- // The demand is not added now (in 4.5), to avoid a breaking change. To be considered in the next version.
- /*
- [PermissionSet(SecurityAction.Demand, Unrestricted = true)] // because we use ProtocolInformationReader, which is defined in a non-APTCA assembly; WSATs are not supported in partial trust, so customers should not be broken by this demand
- */
- void ReadExtendedProtocol(MemoryStream mem, uint cbTmProtocolData)
- {
- // Read the WSAT1.0 protoocol identifier
- Guid guid = SerializationUtils.ReadGuid(mem);
- if (guid == PluggableProtocol10.ProtocolGuid || guid == PluggableProtocol11.ProtocolGuid)
- {
- // This is the WS-AT extended whereabouts blob
- this.protocolInfo = new ProtocolInformationReader(mem);
- }
- else
- {
- // Some other gateway protocol... Skip the rest of the data
- SerializationUtils.IncrementPosition(mem, cbTmProtocolData - 16);
- }
- }
- }
- }
|