public byte[] Encode(IntPtr pObj, int formatStringOffset)
        {
            IntPtr buf         = IntPtr.Zero;
            uint   encodedSize = 0;
            IntPtr ndrHandle   = IntPtr.Zero;

            try
            {
                #region init handle and environment

                int rt = PickleNativeMethods.MesEncodeDynBufferHandleCreate(out buf, out encodedSize, out ndrHandle);
                if (rt != PickleError.RPC_S_OK)
                {
                    throw new PickleException(rt, "Failed to encode on given structure and formatStringOffset.");
                }

                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.NdrMesTypeEncode2(
                    ndrHandle,
                    ref __MIDL_TypePicklingInfo,
                    ref stubDesc,
                    format,
                    ref pObj);

                byte[] managedBuf = new byte[encodedSize];
                Marshal.Copy(buf, managedBuf, 0, (int)encodedSize);

                return(managedBuf);
            }
            finally
            {
                if (ndrHandle != IntPtr.Zero)
                {
                    PickleNativeMethods.MesHandleFree(ndrHandle);
                    //Ignore error
                }
                if (stubDesc.pHandle != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(stubDesc.pHandle);
                    stubDesc.pHandle = IntPtr.Zero;
                }
            }
        }
        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;
                }
            }
        }