public T Decode <T>(byte[] buffer, int index, int count, int formatStringOffset, bool force32Bit, int alignment) where T : struct
        {
            PicklePtrToStructure converter = delegate(IntPtr ptr)
            {
                return(TypeMarshal.ToStruct <T>(ptr, force32Bit, alignment));
            };

            return((T)Decode(converter, buffer, index, count, formatStringOffset));
        }
        public object Decode(PicklePtrToStructure converter, byte[] buffer, int index, int count, int formatStringOffset)
        {
            if (converter == null)
            {
                throw new ArgumentNullException("converter");
            }
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (index < 0 || index >= buffer.Length)
            {
                throw new ArgumentOutOfRangeException("index", "index is out of range");
            }
            if (count < 0 || (index + count) > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("count", "count is out of range");
            }


            IntPtr ndrHandle = IntPtr.Zero;
            IntPtr pObj      = IntPtr.Zero;
            IntPtr pBuf      = IntPtr.Zero;

            try
            {
                #region init handle and environment

                pBuf = Marshal.AllocHGlobal(buffer.Length);
                Marshal.Copy(buffer, index, pBuf, count);

                int rt = PickleNativeMethods.MesDecodeBufferHandleCreate(pBuf, (uint)buffer.Length, out ndrHandle);
                if (rt != PickleError.RPC_S_OK)
                {
                    throw new PickleException(rt, "Failed to create handle on given buffer.");
                }

                if (stubDesc.pHandle != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(stubDesc.pHandle);
                    stubDesc.pHandle = IntPtr.Zero;
                }
                stubDesc.pHandle = Marshal.AllocHGlobal(Marshal.SizeOf(ndrHandle));
                Marshal.WriteIntPtr(stubDesc.pHandle, ndrHandle);

                #endregion

                byte[] format = new byte[typeFormatString.Length - formatStringOffset];
                Buffer.BlockCopy(typeFormatString, formatStringOffset, format, 0, format.Length);

                PickleNativeMethods.NdrMesTypeDecode2(
                    ndrHandle,
                    ref __MIDL_TypePicklingInfo,
                    ref stubDesc,
                    format,
                    ref pObj);

                if (pObj == IntPtr.Zero)
                {
                    throw new PickleException("Failed to decode on given buffer and formatStringOffset.");
                }
                return(converter(pObj));
            }
            finally
            {
                if (ndrHandle != IntPtr.Zero)
                {
                    PickleNativeMethods.MesHandleFree(ndrHandle);
                    //Ignore error
                }
                if (stubDesc.pHandle != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(stubDesc.pHandle);
                    stubDesc.pHandle = IntPtr.Zero;
                }
                if (pObj != IntPtr.Zero)
                {
                    MIDL_user_free(pObj);
                    pObj = IntPtr.Zero;
                }
                if (pBuf != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pBuf);
                    pBuf = IntPtr.Zero;
                }
            }
        }