/// <summary>
        /// Callback function to allocate memory, used by NDR engine.
        /// Copied from midl.exe generated stub code.
        /// </summary>
        /// <param name="s">Buffer size.</param>
        /// <returns>Pointer to allocated memory.</returns>
        private static IntPtr MIDL_user_allocate(uint s)
        {
            IntPtr pcAllocated = Marshal.AllocHGlobal((int)s + 15);
            IntPtr pcUserPtr;

            // NDR engine will pad buffer according to NDR standard,
            // and leaves the padding as uninitialized.
            // So, to get consistency across test runs,
            // we must manually fill the allocated buffer with 0.
            for (int i = 0; i < (int)s + 15; i++)
            {
                Marshal.WriteByte(IntPtrUtility.Add(pcAllocated, i), 0x0);
            }

            // align to 8
            pcUserPtr = IntPtrUtility.Align(pcAllocated, 8);
            if (pcUserPtr == pcAllocated)
            {
                pcUserPtr = IntPtrUtility.Add(pcAllocated, 8);
            }

            // record the offset
            byte offset = (byte)IntPtrUtility.CalculateOffset(pcUserPtr, pcAllocated);

            Marshal.WriteByte(IntPtrUtility.Add(pcUserPtr, -1), offset);

            return(pcUserPtr);
        }
        /// <summary>
        /// Unmarshal a primitive type.
        /// </summary>
        /// <param name="type">Data type</param>
        /// <returns>Pointer to memory where pointer be unmarshalled.</returns>
        private IntPtr NdrUnmarshal(Type type)
        {
            int    size   = Marshal.SizeOf(type);
            int    offset = Marshal.OffsetOf(typeof(NativeMethods.MIDL_STUB_MESSAGE), "Buffer").ToInt32();
            IntPtr ptr    = Marshal.ReadIntPtr(pStubMsg, offset);

            ptr = IntPtrUtility.Align(ptr, size);
            Marshal.WriteIntPtr(
                pStubMsg,
                offset,
                IntPtrUtility.Add(ptr, size));
            return(ptr);
        }
        public IntPtr NdrContextHandleUnmarshall(IntPtr contextHandle, int formatStringOffset)
        {
            // offset + 1 contains the flag of isHandlePtr.
            // offset + 3 contains the flag of isHandleComplex.
            IntPtr pFormat     = IntPtrUtility.Add(stubDesc.pFormatTypes, formatStringOffset + 1);
            bool   isHandlePtr = (Marshal.ReadByte(pFormat) & 0x80) != 0;

            pFormat = IntPtrUtility.Add(stubDesc.pFormatTypes, formatStringOffset + 3);
            bool isHandleComplex = (Marshal.ReadByte(pFormat) & 0x80) != 0;

            if ((isHandleComplex || isHandlePtr) && contextHandle != IntPtr.Zero)
            {
                contextHandle = Marshal.ReadIntPtr(contextHandle);
            }

            //Release old context handle.
            if (contextHandle != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(contextHandle);
            }

            //Unmarshal
            int    offset = Marshal.OffsetOf(typeof(NativeMethods.MIDL_STUB_MESSAGE), "Buffer").ToInt32();
            IntPtr ptr    = Marshal.ReadIntPtr(pStubMsg, offset);

            ptr = IntPtrUtility.Align(ptr, CONTEXT_HANDLE_ALIGNMENT);
            Marshal.WriteIntPtr(
                pStubMsg,
                offset,
                IntPtrUtility.Add(ptr, CONTEXT_HANDLE_WIRE_SIZE));

            bool isZeroContextHandle = true;

            for (int i = 0; i < CONTEXT_HANDLE_WIRE_SIZE; i += sizeof(Int32))
            {
                if (Marshal.ReadInt32(IntPtrUtility.Add(ptr, i)) != 0)
                {
                    isZeroContextHandle = false;
                    break;
                }
            }

            IntPtr contextPtr;

            if (isZeroContextHandle)
            {
                contextPtr = IntPtr.Zero;
            }
            else
            {
                contextPtr = Marshal.AllocHGlobal(CONTEXT_HANDLE_WIRE_SIZE);
                NativeMethods.RtlMoveMemory(contextPtr, ptr, CONTEXT_HANDLE_WIRE_SIZE);
            }

            if (isHandleComplex || isHandlePtr)
            {
                ptr = Marshal.AllocHGlobal(IntPtr.Size);
                FreeMemoryAtDispose(ptr);
                Marshal.WriteIntPtr(ptr, contextPtr);
                contextPtr = ptr;
            }

            return(contextPtr);
        }