ActiveXMessageFormatter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Messaging / System / Messaging / ActiveXMessageFormatter.cs / 1305376 / ActiveXMessageFormatter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Messaging { 
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.InteropServices;
    using System.Text; 
    using System.Runtime.Serialization;
    using System.Diagnostics;
    using System;
    using System.IO; 
    using System.Globalization;
    using System.ComponentModel; 
    using System.Messaging.Interop; 

    ///  
    /// 
    ///    
    ///       Formatter class that serializes and deserializes
    ///       primitives, classes, enumeration, and other objects into and from  
    ///       messages using binary format.
    ///     
    ///  
    public class ActiveXMessageFormatter : IMessageFormatter {
        internal const short VT_ARRAY = 0x2000; 
        internal const short VT_BOOL = 11;
        internal const short VT_BSTR = 8;
        internal const short VT_CLSID = 72;
        internal const short VT_CY = 6; 
        internal const short VT_DATE = 7;
        internal const short VT_I1 = 16; 
        internal const short VT_I2 = 2; 
        internal const short VT_I4 = 3;
        internal const short VT_I8 = 20; 
        internal const short VT_LPSTR = 30;
        internal const short VT_LPWSTR = 31;
        internal const short VT_NULL = 1;
        internal const short VT_R4 = 4; 
        internal const short VT_R8 = 5;
        internal const short VT_STREAMED_OBJECT = 68; 
        internal const short VT_STORED_OBJECT = 69; 
        internal const short VT_UI1 = 17;
        internal const short VT_UI2 = 18; 
        internal const short VT_UI4 = 19;
        internal const short VT_UI8 = 21;
        internal const short VT_VECTOR = 0x1000;
        private byte[] internalBuffer; 
        private UnicodeEncoding unicodeEncoding;
        private ASCIIEncoding asciiEncoding; 
        private char[] internalCharBuffer; 

        ///  
        /// 
        ///    When this method is called, the formatter will attempt to determine
        ///    if the contents of the message are something the formatter can deal with.
        ///  
        public bool CanRead(Message message) {
            if (message == null) 
                throw new ArgumentNullException("message"); 

            int variantType = message.BodyType; 
            if (variantType != VT_BOOL && variantType != VT_CLSID &&
                variantType != VT_CY && variantType != VT_DATE &&
                variantType != VT_I1 && variantType != VT_UI1 &&
                variantType != VT_I2 && variantType != VT_UI2 && 
                variantType != VT_I4 && variantType != VT_UI4 &&
                variantType != VT_I8 && variantType != VT_UI8 && 
                variantType != VT_NULL && variantType != VT_R4 && 
                variantType != VT_I8 && variantType != VT_STREAMED_OBJECT &&
                variantType != VT_STORED_OBJECT && 
                variantType != (VT_VECTOR | VT_UI1) &&
                variantType != VT_LPSTR && variantType != VT_LPWSTR &&
                variantType != VT_BSTR && variantType != VT_R8)
                return false; 

            return true; 
        } 

        ///  
        /// 
        ///    This method is needed to improve scalability on Receive and ReceiveAsync scenarios.  Not requiring
        ///     thread safety on read and write.
        ///  
        public object Clone() {
            return new ActiveXMessageFormatter(); 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        public static void InitStreamedObject(object streamedObject) { 
            IPersistStreamInit persistStreamInit = streamedObject as IPersistStreamInit;
            if (persistStreamInit != null) 
                persistStreamInit.InitNew(); 
        }
 
        /// 
        /// 
        ///    This method is used to read the contents from the given message
        ///     and create an object. 
        /// 
        public object Read(Message message) { 
            if (message == null) 
                throw new ArgumentNullException("message");
 
            Stream stream;
            byte[] bytes;
            byte[] newBytes;
            int size; 
            int variantType = message.BodyType;
            switch (variantType) { 
                case VT_LPSTR: 
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE); 

                    if (this.internalCharBuffer == null || this.internalCharBuffer.Length < size)
                        this.internalCharBuffer = new char[size];
 
                    if (asciiEncoding == null)
                        this.asciiEncoding = new ASCIIEncoding(); 
 
                    this.asciiEncoding.GetChars(bytes, 0, size, this.internalCharBuffer, 0);
                    return new String(this.internalCharBuffer, 0, size); 
                case VT_BSTR:
                case VT_LPWSTR:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE) / 2; 

                    if (this.internalCharBuffer == null || this.internalCharBuffer.Length < size) 
                        this.internalCharBuffer = new char[size]; 

                    if (unicodeEncoding == null) 
                        this.unicodeEncoding = new UnicodeEncoding();

                    this.unicodeEncoding.GetChars(bytes, 0, size * 2, this.internalCharBuffer, 0);
                    return new String(this.internalCharBuffer, 0, size); 
                case VT_VECTOR | VT_UI1:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE); 
                    newBytes = new byte[size];
                    Array.Copy(bytes, newBytes, size); 

                    return newBytes;
                case VT_BOOL:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    newBytes = new byte[1];
                    Array.Copy(bytes, newBytes, 1); 
                    if (bytes[0] != 0) 
                        return true;
 
                    return false;
                case VT_CLSID:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    newBytes = new byte[16]; 
                    Array.Copy(bytes, newBytes, 16);
                    return new Guid(newBytes); 
                case VT_CY: 
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    newBytes = new byte[8]; 
                    Array.Copy(bytes, newBytes, 8);
                    return Decimal.FromOACurrency(BitConverter.ToInt64(newBytes, 0));
                case VT_DATE:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    newBytes = new byte[8];
                    Array.Copy(bytes, newBytes, 8); 
                    return new DateTime(BitConverter.ToInt64(newBytes, 0)); 
                case VT_I1:
                case VT_UI1: 
                    stream = message.BodyStream;
                    bytes = new byte[1];
                    stream.Read(bytes, 0, 1);
                    return bytes[0]; 
                case VT_I2:
                    stream = message.BodyStream; 
                    bytes = new byte[2]; 
                    stream.Read(bytes, 0, 2);
                    return BitConverter.ToInt16(bytes, 0); 
                case VT_UI2:
                    stream = message.BodyStream;
                    bytes = new byte[2];
                    stream.Read(bytes, 0, 2); 
                    return BitConverter.ToUInt16(bytes, 0);
                case VT_I4: 
                    stream = message.BodyStream; 
                    bytes = new byte[4];
                    stream.Read(bytes, 0, 4); 
                    return BitConverter.ToInt32(bytes, 0);
                case VT_UI4:
                    stream = message.BodyStream;
                    bytes = new byte[4]; 
                    stream.Read(bytes, 0, 4);
                    return BitConverter.ToUInt32(bytes, 0); 
                case VT_I8: 
                    stream = message.BodyStream;
                    bytes = new byte[8]; 
                    stream.Read(bytes, 0, 8);
                    return BitConverter.ToInt64(bytes, 0);
                case VT_UI8:
                    stream = message.BodyStream; 
                    bytes = new byte[8];
                    stream.Read(bytes, 0, 8); 
                    return BitConverter.ToUInt64(bytes, 0); 
                case VT_R4:
                    stream = message.BodyStream; 
                    bytes = new byte[4];
                    stream.Read(bytes, 0, 4);
                    return BitConverter.ToSingle(bytes, 0);
                case VT_R8: 
                    stream = message.BodyStream;
                    bytes = new byte[8]; 
                    stream.Read(bytes, 0, 8); 
                    return BitConverter.ToDouble(bytes, 0);
                case VT_NULL: 
                    return null;
                case VT_STREAMED_OBJECT:
                    stream = message.BodyStream;
                    ComStreamFromDataStream comStream = new ComStreamFromDataStream(stream); 
                    return NativeMethods.OleLoadFromStream(comStream, ref NativeMethods.IID_IUnknown);
                case VT_STORED_OBJECT: 
                    throw new NotSupportedException(Res.GetString(Res.StoredObjectsNotSupported)); 
                default:
                    throw new InvalidOperationException(Res.GetString(Res.InvalidTypeDeserialization)); 
            }
        }

        ///  
        /// 
        ///    This method is used to write the given object into the given message. 
        ///     If the formatter cannot understand the given object, an exception is thrown. 
        /// 
        public void Write(Message message, object obj) { 
            if (message == null)
                throw new ArgumentNullException("message");

            Stream stream; 
            int variantType;
            if (obj is string) { 
                int size = ((string)obj).Length * 2; 
                if (this.internalBuffer == null || this.internalBuffer.Length < size)
                    this.internalBuffer = new byte[size]; 

                if (unicodeEncoding == null)
                    this.unicodeEncoding = new UnicodeEncoding();
 
                this.unicodeEncoding.GetBytes(((string)obj).ToCharArray(), 0, size /2, this.internalBuffer, 0);
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.AdjustSize(NativeMethods.MESSAGE_PROPID_BODY, size); 
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, size);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_LPWSTR); 
                return;
            }
            else if (obj is byte[]) {
                byte[] bytes = (byte[])obj; 
                if (this.internalBuffer == null || this.internalBuffer.Length < bytes.Length)
                    this.internalBuffer = new byte[bytes.Length]; 
 
                Array.Copy(bytes, this.internalBuffer, bytes.Length);
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.AdjustSize(NativeMethods.MESSAGE_PROPID_BODY, bytes.Length);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, bytes.Length);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_UI1 | VT_VECTOR);
                return; 
            }
            else if (obj is char[]) { 
                char[] chars = (char[])obj; 
                int size = chars.Length * 2;
                if (this.internalBuffer == null || this.internalBuffer.Length < size) 
                    this.internalBuffer = new byte[size];

                if (unicodeEncoding == null)
                    this.unicodeEncoding = new UnicodeEncoding(); 

                this.unicodeEncoding.GetBytes(chars, 0, size /2, this.internalBuffer, 0); 
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, size);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_LPWSTR); 
                return;
            }
            else if (obj is byte) {
                stream = new MemoryStream(1); 
                stream.Write(new byte[]{(byte)obj}, 0, 1);
                variantType = VT_UI1; 
            } 
            else if (obj is bool) {
                stream = new MemoryStream(1); 
                if ((bool)obj)
                    stream.Write(new byte[]{0xff}, 0, 1);
                else
                    stream.Write(new byte[]{0x00}, 0, 1); 
                variantType = VT_BOOL;
            } 
            else if (obj is char) { 
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((Char)obj); 
                stream.Write(bytes, 0, 2);
                variantType = VT_UI2;
            }
            else if (obj is Decimal) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes(Decimal.ToOACurrency((Decimal)obj)); 
                stream.Write(bytes, 0, 8); 
                variantType = VT_CY;
            } 
            else if (obj is DateTime) {
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes(((DateTime)obj).Ticks);
                stream.Write(bytes, 0, 8); 
                variantType = VT_DATE;
            } 
            else if (obj is Double) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((Double)obj); 
                stream.Write(bytes, 0, 8);
                variantType = VT_R8;
            }
            else if (obj is Int16) { 
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((short)obj); 
                stream.Write(bytes, 0, 2); 
                variantType = VT_I2;
            } 
            else if (obj is UInt16) {
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((UInt16)obj);
                stream.Write(bytes, 0, 2); 
                variantType = VT_UI2;
            } 
            else if (obj is Int32) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((int)obj); 
                stream.Write(bytes, 0, 4);
                variantType = VT_I4;
            }
            else if (obj is UInt32) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((UInt32)obj); 
                stream.Write(bytes, 0, 4); 
                variantType = VT_UI4;
            } 
            else if (obj is Int64) {
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((Int64)obj);
                stream.Write(bytes, 0, 8); 
                variantType = VT_I8;
            } 
            else if (obj is UInt64) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((UInt64)obj); 
                stream.Write(bytes, 0, 8);
                variantType = VT_UI8;
            }
            else if (obj is Single) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((float)obj); 
                stream.Write(bytes, 0, 4); 
                variantType = VT_R4;
            } 
            else if (obj is IPersistStream) {
                IPersistStream pstream = (IPersistStream) obj;
                ComStreamFromDataStream comStream = new ComStreamFromDataStream(new MemoryStream());
                NativeMethods.OleSaveToStream(pstream, comStream); 
                stream = comStream.GetDataStream();
                variantType = VT_STREAMED_OBJECT; 
            } 
            else if (obj == null) {
                stream = new MemoryStream(); 
                variantType = VT_NULL;			
            }
            else {
                throw new InvalidOperationException(Res.GetString(Res.InvalidTypeSerialization)); 
            }
 
            message.BodyStream = stream; 
            message.BodyType = variantType;
        } 

        [ComVisible(false)]
        private class ComStreamFromDataStream : IStream {
            private Stream dataStream; 

            // to support seeking ahead of the stream length... 
            private long virtualPosition = -1; 

            public ComStreamFromDataStream(Stream dataStream) { 
                if (dataStream == null) throw new ArgumentNullException("dataStream");
                this.dataStream = dataStream;
            }
 

            private void ActualizeVirtualPosition() { 
                if (virtualPosition == -1) return; 

                if (virtualPosition > dataStream.Length) 
                    dataStream.SetLength(virtualPosition);

                dataStream.Position = virtualPosition;
 
                virtualPosition = -1;
            } 
 
            public IStream Clone() {
                NotImplemented(); 
                return null;
            }

            public void Commit(int grfCommitFlags) { 
                dataStream.Flush();
                // Extend the length of the file if needed. 
                ActualizeVirtualPosition(); 
            }
 
            public long CopyTo(IStream pstm, long cb, long[] pcbRead) {
                int bufSize = 4096;
                IntPtr buffer = Marshal.AllocHGlobal((IntPtr)bufSize);
                if (buffer == IntPtr.Zero) throw new OutOfMemoryException(); 
                long written = 0;
                try { 
                    while (written < cb) { 
                        int toRead = bufSize;
                        if (written + toRead > cb) toRead  = (int) (cb - written); 
                        int read = Read(buffer, toRead);
                        if (read == 0) break;
                        if (pstm.Write(buffer, read) != read) {
                            throw EFail(Res.GetString(Res.IncorrectNumberOfBytes)); 
                        }
                        written += read; 
                    } 
                }
                finally { 
                    Marshal.FreeHGlobal(buffer);
                }
                if (pcbRead != null && pcbRead.Length > 0) {
                    pcbRead[0] = written; 
                }
 
                return written; 
            }
 
            public Stream GetDataStream() {
                return dataStream;
            }
 
            public void LockRegion(long libOffset, long cb, int dwLockType) {
            } 
 
            protected static ExternalException EFail(string msg) {
                ExternalException e = new ExternalException(msg, NativeMethods.E_FAIL); 
                throw e;
            }

            protected static void NotImplemented() { 
                ExternalException e = new ExternalException(Res.GetString(Res.NotImplemented), NativeMethods.E_NOTIMPL);
                throw e; 
            } 

            public int Read(IntPtr buf, int length) { 
                byte[] buffer = new byte[length];
                int count = Read(buffer, length);
                Marshal.Copy(buffer, 0, buf, length);
                return count; 
            }
 
            public int Read(byte[] buffer, int length) { 
                ActualizeVirtualPosition();
                return dataStream.Read(buffer, 0, length); 
            }

            public void Revert() {
                NotImplemented(); 
            }
 
            public long Seek(long offset, int origin) { 
                long pos = virtualPosition;
                if (virtualPosition == -1) { 
                    pos = dataStream.Position;
                }
                long len = dataStream.Length;
                switch (origin) { 
                    case NativeMethods.STREAM_SEEK_SET:
                        if (offset <= len) { 
                            dataStream.Position = offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = offset;
                        }
                        break; 
                    case NativeMethods.STREAM_SEEK_END:
                        if (offset <= 0) { 
                            dataStream.Position = len + offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = len + offset;
                        }
                        break; 
                    case NativeMethods.STREAM_SEEK_CUR:
                        if (offset+pos <= len) { 
                            dataStream.Position = pos + offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = offset + pos;
                        }
                        break; 
                }
                if (virtualPosition != -1) { 
                    return virtualPosition; 
                }
                else { 
                    return dataStream.Position;
                }
            }
 
            public void SetSize(long value) {
                dataStream.SetLength(value); 
            } 

            public void Stat(IntPtr pstatstg, int grfStatFlag) { 
                // GpStream has a partial implementation, but it's so partial rather
                // restrict it to use with GDI+
                NotImplemented();
            } 

            public void UnlockRegion(long libOffset, long cb, int dwLockType) { 
            } 

            public int Write(IntPtr buf, int length) { 
                byte[] buffer = new byte[length];
                Marshal.Copy(buf, buffer, 0, length);
                return Write(buffer, length);
            } 

            public int Write(byte[] buffer, int length) { 
                ActualizeVirtualPosition(); 
                dataStream.Write(buffer, 0, length);
                return length; 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Messaging { 
    using System.Runtime.Serialization.Formatters; 
    using System.Runtime.InteropServices;
    using System.Text; 
    using System.Runtime.Serialization;
    using System.Diagnostics;
    using System;
    using System.IO; 
    using System.Globalization;
    using System.ComponentModel; 
    using System.Messaging.Interop; 

    ///  
    /// 
    ///    
    ///       Formatter class that serializes and deserializes
    ///       primitives, classes, enumeration, and other objects into and from  
    ///       messages using binary format.
    ///     
    ///  
    public class ActiveXMessageFormatter : IMessageFormatter {
        internal const short VT_ARRAY = 0x2000; 
        internal const short VT_BOOL = 11;
        internal const short VT_BSTR = 8;
        internal const short VT_CLSID = 72;
        internal const short VT_CY = 6; 
        internal const short VT_DATE = 7;
        internal const short VT_I1 = 16; 
        internal const short VT_I2 = 2; 
        internal const short VT_I4 = 3;
        internal const short VT_I8 = 20; 
        internal const short VT_LPSTR = 30;
        internal const short VT_LPWSTR = 31;
        internal const short VT_NULL = 1;
        internal const short VT_R4 = 4; 
        internal const short VT_R8 = 5;
        internal const short VT_STREAMED_OBJECT = 68; 
        internal const short VT_STORED_OBJECT = 69; 
        internal const short VT_UI1 = 17;
        internal const short VT_UI2 = 18; 
        internal const short VT_UI4 = 19;
        internal const short VT_UI8 = 21;
        internal const short VT_VECTOR = 0x1000;
        private byte[] internalBuffer; 
        private UnicodeEncoding unicodeEncoding;
        private ASCIIEncoding asciiEncoding; 
        private char[] internalCharBuffer; 

        ///  
        /// 
        ///    When this method is called, the formatter will attempt to determine
        ///    if the contents of the message are something the formatter can deal with.
        ///  
        public bool CanRead(Message message) {
            if (message == null) 
                throw new ArgumentNullException("message"); 

            int variantType = message.BodyType; 
            if (variantType != VT_BOOL && variantType != VT_CLSID &&
                variantType != VT_CY && variantType != VT_DATE &&
                variantType != VT_I1 && variantType != VT_UI1 &&
                variantType != VT_I2 && variantType != VT_UI2 && 
                variantType != VT_I4 && variantType != VT_UI4 &&
                variantType != VT_I8 && variantType != VT_UI8 && 
                variantType != VT_NULL && variantType != VT_R4 && 
                variantType != VT_I8 && variantType != VT_STREAMED_OBJECT &&
                variantType != VT_STORED_OBJECT && 
                variantType != (VT_VECTOR | VT_UI1) &&
                variantType != VT_LPSTR && variantType != VT_LPWSTR &&
                variantType != VT_BSTR && variantType != VT_R8)
                return false; 

            return true; 
        } 

        ///  
        /// 
        ///    This method is needed to improve scalability on Receive and ReceiveAsync scenarios.  Not requiring
        ///     thread safety on read and write.
        ///  
        public object Clone() {
            return new ActiveXMessageFormatter(); 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        public static void InitStreamedObject(object streamedObject) { 
            IPersistStreamInit persistStreamInit = streamedObject as IPersistStreamInit;
            if (persistStreamInit != null) 
                persistStreamInit.InitNew(); 
        }
 
        /// 
        /// 
        ///    This method is used to read the contents from the given message
        ///     and create an object. 
        /// 
        public object Read(Message message) { 
            if (message == null) 
                throw new ArgumentNullException("message");
 
            Stream stream;
            byte[] bytes;
            byte[] newBytes;
            int size; 
            int variantType = message.BodyType;
            switch (variantType) { 
                case VT_LPSTR: 
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE); 

                    if (this.internalCharBuffer == null || this.internalCharBuffer.Length < size)
                        this.internalCharBuffer = new char[size];
 
                    if (asciiEncoding == null)
                        this.asciiEncoding = new ASCIIEncoding(); 
 
                    this.asciiEncoding.GetChars(bytes, 0, size, this.internalCharBuffer, 0);
                    return new String(this.internalCharBuffer, 0, size); 
                case VT_BSTR:
                case VT_LPWSTR:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE) / 2; 

                    if (this.internalCharBuffer == null || this.internalCharBuffer.Length < size) 
                        this.internalCharBuffer = new char[size]; 

                    if (unicodeEncoding == null) 
                        this.unicodeEncoding = new UnicodeEncoding();

                    this.unicodeEncoding.GetChars(bytes, 0, size * 2, this.internalCharBuffer, 0);
                    return new String(this.internalCharBuffer, 0, size); 
                case VT_VECTOR | VT_UI1:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    size = message.properties.GetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE); 
                    newBytes = new byte[size];
                    Array.Copy(bytes, newBytes, size); 

                    return newBytes;
                case VT_BOOL:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    newBytes = new byte[1];
                    Array.Copy(bytes, newBytes, 1); 
                    if (bytes[0] != 0) 
                        return true;
 
                    return false;
                case VT_CLSID:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    newBytes = new byte[16]; 
                    Array.Copy(bytes, newBytes, 16);
                    return new Guid(newBytes); 
                case VT_CY: 
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY);
                    newBytes = new byte[8]; 
                    Array.Copy(bytes, newBytes, 8);
                    return Decimal.FromOACurrency(BitConverter.ToInt64(newBytes, 0));
                case VT_DATE:
                    bytes = message.properties.GetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY); 
                    newBytes = new byte[8];
                    Array.Copy(bytes, newBytes, 8); 
                    return new DateTime(BitConverter.ToInt64(newBytes, 0)); 
                case VT_I1:
                case VT_UI1: 
                    stream = message.BodyStream;
                    bytes = new byte[1];
                    stream.Read(bytes, 0, 1);
                    return bytes[0]; 
                case VT_I2:
                    stream = message.BodyStream; 
                    bytes = new byte[2]; 
                    stream.Read(bytes, 0, 2);
                    return BitConverter.ToInt16(bytes, 0); 
                case VT_UI2:
                    stream = message.BodyStream;
                    bytes = new byte[2];
                    stream.Read(bytes, 0, 2); 
                    return BitConverter.ToUInt16(bytes, 0);
                case VT_I4: 
                    stream = message.BodyStream; 
                    bytes = new byte[4];
                    stream.Read(bytes, 0, 4); 
                    return BitConverter.ToInt32(bytes, 0);
                case VT_UI4:
                    stream = message.BodyStream;
                    bytes = new byte[4]; 
                    stream.Read(bytes, 0, 4);
                    return BitConverter.ToUInt32(bytes, 0); 
                case VT_I8: 
                    stream = message.BodyStream;
                    bytes = new byte[8]; 
                    stream.Read(bytes, 0, 8);
                    return BitConverter.ToInt64(bytes, 0);
                case VT_UI8:
                    stream = message.BodyStream; 
                    bytes = new byte[8];
                    stream.Read(bytes, 0, 8); 
                    return BitConverter.ToUInt64(bytes, 0); 
                case VT_R4:
                    stream = message.BodyStream; 
                    bytes = new byte[4];
                    stream.Read(bytes, 0, 4);
                    return BitConverter.ToSingle(bytes, 0);
                case VT_R8: 
                    stream = message.BodyStream;
                    bytes = new byte[8]; 
                    stream.Read(bytes, 0, 8); 
                    return BitConverter.ToDouble(bytes, 0);
                case VT_NULL: 
                    return null;
                case VT_STREAMED_OBJECT:
                    stream = message.BodyStream;
                    ComStreamFromDataStream comStream = new ComStreamFromDataStream(stream); 
                    return NativeMethods.OleLoadFromStream(comStream, ref NativeMethods.IID_IUnknown);
                case VT_STORED_OBJECT: 
                    throw new NotSupportedException(Res.GetString(Res.StoredObjectsNotSupported)); 
                default:
                    throw new InvalidOperationException(Res.GetString(Res.InvalidTypeDeserialization)); 
            }
        }

        ///  
        /// 
        ///    This method is used to write the given object into the given message. 
        ///     If the formatter cannot understand the given object, an exception is thrown. 
        /// 
        public void Write(Message message, object obj) { 
            if (message == null)
                throw new ArgumentNullException("message");

            Stream stream; 
            int variantType;
            if (obj is string) { 
                int size = ((string)obj).Length * 2; 
                if (this.internalBuffer == null || this.internalBuffer.Length < size)
                    this.internalBuffer = new byte[size]; 

                if (unicodeEncoding == null)
                    this.unicodeEncoding = new UnicodeEncoding();
 
                this.unicodeEncoding.GetBytes(((string)obj).ToCharArray(), 0, size /2, this.internalBuffer, 0);
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.AdjustSize(NativeMethods.MESSAGE_PROPID_BODY, size); 
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, size);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_LPWSTR); 
                return;
            }
            else if (obj is byte[]) {
                byte[] bytes = (byte[])obj; 
                if (this.internalBuffer == null || this.internalBuffer.Length < bytes.Length)
                    this.internalBuffer = new byte[bytes.Length]; 
 
                Array.Copy(bytes, this.internalBuffer, bytes.Length);
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.AdjustSize(NativeMethods.MESSAGE_PROPID_BODY, bytes.Length);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, bytes.Length);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_UI1 | VT_VECTOR);
                return; 
            }
            else if (obj is char[]) { 
                char[] chars = (char[])obj; 
                int size = chars.Length * 2;
                if (this.internalBuffer == null || this.internalBuffer.Length < size) 
                    this.internalBuffer = new byte[size];

                if (unicodeEncoding == null)
                    this.unicodeEncoding = new UnicodeEncoding(); 

                this.unicodeEncoding.GetBytes(chars, 0, size /2, this.internalBuffer, 0); 
                message.properties.SetUI1Vector(NativeMethods.MESSAGE_PROPID_BODY, this.internalBuffer); 
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_SIZE, size);
                message.properties.SetUI4(NativeMethods.MESSAGE_PROPID_BODY_TYPE, VT_LPWSTR); 
                return;
            }
            else if (obj is byte) {
                stream = new MemoryStream(1); 
                stream.Write(new byte[]{(byte)obj}, 0, 1);
                variantType = VT_UI1; 
            } 
            else if (obj is bool) {
                stream = new MemoryStream(1); 
                if ((bool)obj)
                    stream.Write(new byte[]{0xff}, 0, 1);
                else
                    stream.Write(new byte[]{0x00}, 0, 1); 
                variantType = VT_BOOL;
            } 
            else if (obj is char) { 
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((Char)obj); 
                stream.Write(bytes, 0, 2);
                variantType = VT_UI2;
            }
            else if (obj is Decimal) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes(Decimal.ToOACurrency((Decimal)obj)); 
                stream.Write(bytes, 0, 8); 
                variantType = VT_CY;
            } 
            else if (obj is DateTime) {
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes(((DateTime)obj).Ticks);
                stream.Write(bytes, 0, 8); 
                variantType = VT_DATE;
            } 
            else if (obj is Double) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((Double)obj); 
                stream.Write(bytes, 0, 8);
                variantType = VT_R8;
            }
            else if (obj is Int16) { 
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((short)obj); 
                stream.Write(bytes, 0, 2); 
                variantType = VT_I2;
            } 
            else if (obj is UInt16) {
                stream = new MemoryStream(2);
                byte[] bytes = BitConverter.GetBytes((UInt16)obj);
                stream.Write(bytes, 0, 2); 
                variantType = VT_UI2;
            } 
            else if (obj is Int32) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((int)obj); 
                stream.Write(bytes, 0, 4);
                variantType = VT_I4;
            }
            else if (obj is UInt32) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((UInt32)obj); 
                stream.Write(bytes, 0, 4); 
                variantType = VT_UI4;
            } 
            else if (obj is Int64) {
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((Int64)obj);
                stream.Write(bytes, 0, 8); 
                variantType = VT_I8;
            } 
            else if (obj is UInt64) { 
                stream = new MemoryStream(8);
                byte[] bytes = BitConverter.GetBytes((UInt64)obj); 
                stream.Write(bytes, 0, 8);
                variantType = VT_UI8;
            }
            else if (obj is Single) { 
                stream = new MemoryStream(4);
                byte[] bytes = BitConverter.GetBytes((float)obj); 
                stream.Write(bytes, 0, 4); 
                variantType = VT_R4;
            } 
            else if (obj is IPersistStream) {
                IPersistStream pstream = (IPersistStream) obj;
                ComStreamFromDataStream comStream = new ComStreamFromDataStream(new MemoryStream());
                NativeMethods.OleSaveToStream(pstream, comStream); 
                stream = comStream.GetDataStream();
                variantType = VT_STREAMED_OBJECT; 
            } 
            else if (obj == null) {
                stream = new MemoryStream(); 
                variantType = VT_NULL;			
            }
            else {
                throw new InvalidOperationException(Res.GetString(Res.InvalidTypeSerialization)); 
            }
 
            message.BodyStream = stream; 
            message.BodyType = variantType;
        } 

        [ComVisible(false)]
        private class ComStreamFromDataStream : IStream {
            private Stream dataStream; 

            // to support seeking ahead of the stream length... 
            private long virtualPosition = -1; 

            public ComStreamFromDataStream(Stream dataStream) { 
                if (dataStream == null) throw new ArgumentNullException("dataStream");
                this.dataStream = dataStream;
            }
 

            private void ActualizeVirtualPosition() { 
                if (virtualPosition == -1) return; 

                if (virtualPosition > dataStream.Length) 
                    dataStream.SetLength(virtualPosition);

                dataStream.Position = virtualPosition;
 
                virtualPosition = -1;
            } 
 
            public IStream Clone() {
                NotImplemented(); 
                return null;
            }

            public void Commit(int grfCommitFlags) { 
                dataStream.Flush();
                // Extend the length of the file if needed. 
                ActualizeVirtualPosition(); 
            }
 
            public long CopyTo(IStream pstm, long cb, long[] pcbRead) {
                int bufSize = 4096;
                IntPtr buffer = Marshal.AllocHGlobal((IntPtr)bufSize);
                if (buffer == IntPtr.Zero) throw new OutOfMemoryException(); 
                long written = 0;
                try { 
                    while (written < cb) { 
                        int toRead = bufSize;
                        if (written + toRead > cb) toRead  = (int) (cb - written); 
                        int read = Read(buffer, toRead);
                        if (read == 0) break;
                        if (pstm.Write(buffer, read) != read) {
                            throw EFail(Res.GetString(Res.IncorrectNumberOfBytes)); 
                        }
                        written += read; 
                    } 
                }
                finally { 
                    Marshal.FreeHGlobal(buffer);
                }
                if (pcbRead != null && pcbRead.Length > 0) {
                    pcbRead[0] = written; 
                }
 
                return written; 
            }
 
            public Stream GetDataStream() {
                return dataStream;
            }
 
            public void LockRegion(long libOffset, long cb, int dwLockType) {
            } 
 
            protected static ExternalException EFail(string msg) {
                ExternalException e = new ExternalException(msg, NativeMethods.E_FAIL); 
                throw e;
            }

            protected static void NotImplemented() { 
                ExternalException e = new ExternalException(Res.GetString(Res.NotImplemented), NativeMethods.E_NOTIMPL);
                throw e; 
            } 

            public int Read(IntPtr buf, int length) { 
                byte[] buffer = new byte[length];
                int count = Read(buffer, length);
                Marshal.Copy(buffer, 0, buf, length);
                return count; 
            }
 
            public int Read(byte[] buffer, int length) { 
                ActualizeVirtualPosition();
                return dataStream.Read(buffer, 0, length); 
            }

            public void Revert() {
                NotImplemented(); 
            }
 
            public long Seek(long offset, int origin) { 
                long pos = virtualPosition;
                if (virtualPosition == -1) { 
                    pos = dataStream.Position;
                }
                long len = dataStream.Length;
                switch (origin) { 
                    case NativeMethods.STREAM_SEEK_SET:
                        if (offset <= len) { 
                            dataStream.Position = offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = offset;
                        }
                        break; 
                    case NativeMethods.STREAM_SEEK_END:
                        if (offset <= 0) { 
                            dataStream.Position = len + offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = len + offset;
                        }
                        break; 
                    case NativeMethods.STREAM_SEEK_CUR:
                        if (offset+pos <= len) { 
                            dataStream.Position = pos + offset; 
                            virtualPosition = -1;
                        } 
                        else {
                            virtualPosition = offset + pos;
                        }
                        break; 
                }
                if (virtualPosition != -1) { 
                    return virtualPosition; 
                }
                else { 
                    return dataStream.Position;
                }
            }
 
            public void SetSize(long value) {
                dataStream.SetLength(value); 
            } 

            public void Stat(IntPtr pstatstg, int grfStatFlag) { 
                // GpStream has a partial implementation, but it's so partial rather
                // restrict it to use with GDI+
                NotImplemented();
            } 

            public void UnlockRegion(long libOffset, long cb, int dwLockType) { 
            } 

            public int Write(IntPtr buf, int length) { 
                byte[] buffer = new byte[length];
                Marshal.Copy(buf, buffer, 0, length);
                return Write(buffer, length);
            } 

            public int Write(byte[] buffer, int length) { 
                ActualizeVirtualPosition(); 
                dataStream.Write(buffer, 0, length);
                return length; 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK