private static Res GetLoader()
 {
     if (loader == null)
     {
         Res res = new Res();
         Interlocked.CompareExchange<Res>(ref loader, res, null);
     }
     return loader;
 }
        /// <include file='doc\ActiveXMessageFormatter.uex' path='docs/doc[@for="ActiveXMessageFormatter.Write"]/*' />
        /// <devdoc>
        ///    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.
        /// </devdoc>
        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;
        }
            protected static void NotImplemented()
            {
                ExternalException e = new ExternalException(Res.GetString(Res.NotImplemented), NativeMethods.E_NOTIMPL);

                throw e;
            }
        /// <include file='doc\ActiveXMessageFormatter.uex' path='docs/doc[@for="ActiveXMessageFormatter.Read"]/*' />
        /// <devdoc>
        ///    This method is used to read the contents from the given message
        ///     and create an object.
        /// </devdoc>
        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));
            }
        }