File: System\ServiceModel\Channels\MsmqInputMessage.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.   
//------------------------------------------------------------  
 
namespace System.ServiceModel.Channels
{
    class MsmqInputMessage : NativeMsmqMessage
    {
        BufferProperty senderId;
        IntProperty senderIdLength;
        LongProperty lookupId;
        IntProperty abortCount;
        IntProperty moveCount;
        BufferProperty senderCertificate;
        IntProperty senderCertificateLength;
        IntProperty lastMovedTime;
        BufferProperty body;
        IntProperty bodyLength;
        BufferProperty messageId;
        ShortProperty cls;
        int maxBufferSize;
        const int maxSize = 4 * 1024 * 1024;
        const int initialBodySize = 4096;
        const int initialSenderIdSize = 256;
        const int initialCertificateSize = 4096;
 
        public MsmqInputMessage()
            : this(0, maxSize)
        {
        }
 
        public MsmqInputMessage(int maxBufferSize)
            : this(0, maxBufferSize)
        {
        }
 
        protected MsmqInputMessage(int additionalPropertyCount, int maxBufferSize)
            : this(additionalPropertyCount, new SizeQuota(maxBufferSize))
        {
        }
 
        protected MsmqInputMessage(int additionalPropertyCount, SizeQuota bufferSizeQuota)
            : base(12 + additionalPropertyCount)
        {
            this.maxBufferSize = bufferSizeQuota.MaxSize;
            this.body = new BufferProperty(this, UnsafeNativeMethods.PROPID_M_BODY,
                bufferSizeQuota.AllocIfAvailable(initialBodySize));
            this.bodyLength = new IntProperty(this, UnsafeNativeMethods.PROPID_M_BODY_SIZE);
            this.messageId = new BufferProperty(this, UnsafeNativeMethods.PROPID_M_MSGID,
                UnsafeNativeMethods.PROPID_M_MSGID_SIZE);
            this.lookupId = new LongProperty(this, UnsafeNativeMethods.PROPID_M_LOOKUPID);
            this.cls = new ShortProperty(this, UnsafeNativeMethods.PROPID_M_CLASS);
            this.senderId = new BufferProperty(this, UnsafeNativeMethods.PROPID_M_SENDERID, initialSenderIdSize);
            this.senderIdLength = new IntProperty(this, UnsafeNativeMethods.PROPID_M_SENDERID_LEN);
            this.senderCertificate = new BufferProperty(this, UnsafeNativeMethods.PROPID_M_SENDER_CERT,
                bufferSizeQuota.AllocIfAvailable(initialCertificateSize));
            this.senderCertificateLength = new IntProperty(this, UnsafeNativeMethods.PROPID_M_SENDER_CERT_LEN);
            if (Msmq.IsAdvancedPoisonHandlingSupported)
            {
                this.lastMovedTime = new IntProperty(this, UnsafeNativeMethods.PROPID_M_LAST_MOVE_TIME);
                this.abortCount = new IntProperty(this, UnsafeNativeMethods.PROPID_M_ABORT_COUNT);
                this.moveCount = new IntProperty(this, UnsafeNativeMethods.PROPID_M_MOVE_COUNT);
            }
        }
 
        public override void GrowBuffers()
        {
            OnGrowBuffers(new SizeQuota(this.maxBufferSize));
        }
 
        protected virtual void OnGrowBuffers(SizeQuota bufferSizeQuota)
        {
            bufferSizeQuota.Alloc(this.senderIdLength.Value);
            this.senderId.EnsureBufferLength(this.senderIdLength.Value);
 
            bufferSizeQuota.Alloc(this.senderCertificateLength.Value);
            this.senderCertificate.EnsureBufferLength(this.senderCertificateLength.Value);
 
            bufferSizeQuota.Alloc(this.bodyLength.Value);
            this.body.EnsureBufferLength(this.bodyLength.Value);
        }
 
        public BufferProperty SenderId
        {
            get { return this.senderId; }
        }
 
        public IntProperty SenderIdLength
        {
            get { return this.senderIdLength; }
        }
 
        public LongProperty LookupId
        {
            get { return this.lookupId; }
        }
 
        public IntProperty AbortCount
        {
            get { return this.abortCount; }
        }
 
        public IntProperty MoveCount
        {
            get { return this.moveCount; }
        }
 
        public BufferProperty SenderCertificate
        {
            get { return this.senderCertificate; }
        }
 
        public IntProperty SenderCertificateLength
        {
            get { return this.senderCertificateLength; }
        }
 
        public IntProperty LastMovedTime
        {
            get { return this.lastMovedTime; }
        }
 
        public BufferProperty Body
        {
            get { return this.body; }
        }
 
        public IntProperty BodyLength
        {
            get { return this.bodyLength; }
        }
 
        public BufferProperty MessageId
        {
            get { return this.messageId; }
        }
 
        public ShortProperty Class
        {
            get { return this.cls; }
        }
 
        protected class SizeQuota
        {
            int remainingSize;
            int maxSize;
 
            public SizeQuota(int maxSize)
            {
                this.maxSize = maxSize;
                this.remainingSize = maxSize;
            }
 
            public int MaxSize
            {
                get { return this.maxSize; }
            }
 
            public void Alloc(int requiredSize)
            {
                if (requiredSize > this.remainingSize)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(MaxMessageSizeStream.CreateMaxReceivedMessageSizeExceededException(this.maxSize));
                }
                this.remainingSize -= requiredSize;
            }
 
            public int AllocIfAvailable(int desiredSize)
            {
                int availableSize = Math.Min(desiredSize, this.remainingSize);
                this.remainingSize -= availableSize;
                return availableSize;
            }
        }
    }
}