/// <summary>
        /// constructor.
        /// </summary>
        /// <param name="runtimeTargetPlatform">Runtime platform, x86 or amd64.</param>
        /// <param name="typeFormatString">Type format string generated by MIDL.</param>
        /// <param name="exprEvalRoutines">ExprEvalRoutines generated by MIDL if exists.</param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when typeFormatString is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when runtimeTargetPlatform doesn't match current platform at runtime.
        /// </exception>
        protected RpceStub(
            RpceStubTargetPlatform runtimeTargetPlatform,
            byte[] typeFormatString,
            RpceStubExprEval[] exprEvalRoutines)
        {
            if (typeFormatString == null)
            {
                throw new ArgumentNullException("typeFormatString");
            }
            if ((IntPtr.Size == sizeof(Int32) && (runtimeTargetPlatform & RpceStubTargetPlatform.X86) != RpceStubTargetPlatform.X86) ||
                (IntPtr.Size == sizeof(Int64) && (runtimeTargetPlatform & RpceStubTargetPlatform.Amd64) != RpceStubTargetPlatform.Amd64))
            {
                throw new InvalidOperationException("Invalid target platform.");
            }

            allocatedMemoryList = new List<IntPtr>();

            #region RPC_CLIENT_INTERFACE rpcClientInterface

            NativeMethods.RPC_CLIENT_INTERFACE rpcClientInterface = new NativeMethods.RPC_CLIENT_INTERFACE();
            rpcClientInterface.Length = (uint)Marshal.SizeOf(typeof(NativeMethods.RPC_CLIENT_INTERFACE));

            rpcClientInterface.InterfaceId.SyntaxGUID = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_ID;
            rpcClientInterface.InterfaceId.SyntaxVersion.MajorVersion = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_VERS_MAJOR;
            rpcClientInterface.InterfaceId.SyntaxVersion.MinorVersion = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_VERS_MINOR;

            rpcClientInterface.TransferSyntax.SyntaxGUID = RpceUtility.NDR_INTERFACE_UUID;
            rpcClientInterface.TransferSyntax.SyntaxVersion.MajorVersion = RpceUtility.NDR_INTERFACE_MAJOR_VERSION;
            rpcClientInterface.TransferSyntax.SyntaxVersion.MinorVersion = RpceUtility.NDR_INTERFACE_MINOR_VERSION;

            rpcClientInterface.DispatchTable = IntPtr.Zero;
            rpcClientInterface.RpcProtseqEndpointCount = 0;
            rpcClientInterface.RpcProtseqEndpoint = IntPtr.Zero;
            rpcClientInterface.Reserved = 0;
            rpcClientInterface.InterpreterInfo = IntPtr.Zero;
            rpcClientInterface.Flags = 0x00000000;

            #endregion

            #region MIDL_STUB_DESC stubDesc

            stubDesc = new NativeMethods.MIDL_STUB_DESC();
            stubDesc.RpcInterfaceInformation = Marshal.AllocHGlobal(Marshal.SizeOf(rpcClientInterface));
            Marshal.StructureToPtr(rpcClientInterface, stubDesc.RpcInterfaceInformation, false);

            stubDesc.pfnAllocate = new NativeMethods.PfnAllocate(MIDL_user_allocate);
            stubDesc.pfnFree = new NativeMethods.PfnFree(MIDL_user_free);

            stubDesc.apfnNdrRundownRoutines = IntPtr.Zero;
            stubDesc.aGenericBindingRoutinePairs = IntPtr.Zero;

            if (exprEvalRoutines == null || exprEvalRoutines.Length == 0)
            {
                stubDesc.apfnExprEval = IntPtr.Zero;
            }
            else
            {
                exprEvalList = new List<NativeMethods.EXPR_EVAL>(exprEvalRoutines.Length);
                stubDesc.apfnExprEval = Marshal.AllocHGlobal(IntPtr.Size * exprEvalRoutines.Length);
                for (int i = 0; i < exprEvalRoutines.Length; i++)
                {
                    RpceStubExprEvalCallback callback = new RpceStubExprEvalCallback(this, exprEvalRoutines[i]);
                    NativeMethods.EXPR_EVAL exprEval = new NativeMethods.EXPR_EVAL(callback.EXPR_EVAL);
                    IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(exprEval);
                    Marshal.WriteIntPtr(stubDesc.apfnExprEval, IntPtr.Size * i, funcPtr);

                    //http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getfunctionpointerfordelegate.aspx
                    //Caller must manually keep the delegate from being collected by
                    // the garbage collector from managed code.
                    exprEvalList.Add(exprEval);
                }
            }
            stubDesc.aXmitQuintuple = IntPtr.Zero;

            stubDesc.pFormatTypes = Marshal.AllocHGlobal(typeFormatString.Length);
            Marshal.Copy(typeFormatString, 0, stubDesc.pFormatTypes, typeFormatString.Length);

            stubDesc.fCheckBounds = 0; /* -error bounds_check flag : "midl /error none" */
            stubDesc.Version = 0x50000; /* Ndr library version */
            stubDesc.pMallocFreeStruct = IntPtr.Zero;
            stubDesc.MIDLVersion = 0x70001e6; /* MIDL Version 7.0.486 */
            stubDesc.CommFaultOffsets = IntPtr.Zero;
            stubDesc.aUserMarshalQuadruple = IntPtr.Zero;
            stubDesc.NotifyRoutineTable = IntPtr.Zero;  /* notify & notify_flag routine table */
            stubDesc.mFlags = 0x1; /* MIDL flag */
            stubDesc.CsRoutineTables = IntPtr.Zero; /* cs routines */
            stubDesc.ProxyServerInfo = IntPtr.Zero; /* proxy/server native */
            stubDesc.pExprInfo = IntPtr.Zero; /* Reserved5 */

            #endregion
        }
        /// <summary>
        /// constructor.
        /// </summary>
        /// <param name="runtimeTargetPlatform">Runtime platform, x86 or amd64.</param>
        /// <param name="typeFormatString">Type format string generated by MIDL.</param>
        /// <param name="exprEvalRoutines">ExprEvalRoutines generated by MIDL if exists.</param>
        /// <exception cref="ArgumentNullException">
        /// Thrown when typeFormatString is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when runtimeTargetPlatform doesn't match current platform at runtime.
        /// </exception>
        protected RpceStub(
            RpceStubTargetPlatform runtimeTargetPlatform,
            byte[] typeFormatString,
            RpceStubExprEval[] exprEvalRoutines)
        {
            if (typeFormatString == null)
            {
                throw new ArgumentNullException("typeFormatString");
            }
            if ((IntPtr.Size == sizeof(Int32) && (runtimeTargetPlatform & RpceStubTargetPlatform.X86) != RpceStubTargetPlatform.X86) ||
                (IntPtr.Size == sizeof(Int64) && (runtimeTargetPlatform & RpceStubTargetPlatform.Amd64) != RpceStubTargetPlatform.Amd64))
            {
                throw new InvalidOperationException("Invalid target platform.");
            }

            allocatedMemoryList = new List <IntPtr>();

            #region RPC_CLIENT_INTERFACE rpcClientInterface

            NativeMethods.RPC_CLIENT_INTERFACE rpcClientInterface = new NativeMethods.RPC_CLIENT_INTERFACE();
            rpcClientInterface.Length = (uint)Marshal.SizeOf(typeof(NativeMethods.RPC_CLIENT_INTERFACE));

            rpcClientInterface.InterfaceId.SyntaxGUID = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_ID;
            rpcClientInterface.InterfaceId.SyntaxVersion.MajorVersion = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_VERS_MAJOR;
            rpcClientInterface.InterfaceId.SyntaxVersion.MinorVersion = RpceStubEncoder.RPCE_BIND_ONLY_SERVER.IF_VERS_MINOR;

            rpcClientInterface.TransferSyntax.SyntaxGUID = RpceUtility.NDR_INTERFACE_UUID;
            rpcClientInterface.TransferSyntax.SyntaxVersion.MajorVersion = RpceUtility.NDR_INTERFACE_MAJOR_VERSION;
            rpcClientInterface.TransferSyntax.SyntaxVersion.MinorVersion = RpceUtility.NDR_INTERFACE_MINOR_VERSION;

            rpcClientInterface.DispatchTable           = IntPtr.Zero;
            rpcClientInterface.RpcProtseqEndpointCount = 0;
            rpcClientInterface.RpcProtseqEndpoint      = IntPtr.Zero;
            rpcClientInterface.Reserved        = 0;
            rpcClientInterface.InterpreterInfo = IntPtr.Zero;
            rpcClientInterface.Flags           = 0x00000000;

            #endregion

            #region MIDL_STUB_DESC stubDesc

            stubDesc = new NativeMethods.MIDL_STUB_DESC();
            stubDesc.RpcInterfaceInformation = Marshal.AllocHGlobal(Marshal.SizeOf(rpcClientInterface));
            Marshal.StructureToPtr(rpcClientInterface, stubDesc.RpcInterfaceInformation, false);

            stubDesc.pfnAllocate = new NativeMethods.PfnAllocate(MIDL_user_allocate);
            stubDesc.pfnFree     = new NativeMethods.PfnFree(MIDL_user_free);

            stubDesc.apfnNdrRundownRoutines      = IntPtr.Zero;
            stubDesc.aGenericBindingRoutinePairs = IntPtr.Zero;

            if (exprEvalRoutines == null || exprEvalRoutines.Length == 0)
            {
                stubDesc.apfnExprEval = IntPtr.Zero;
            }
            else
            {
                exprEvalList          = new List <NativeMethods.EXPR_EVAL>(exprEvalRoutines.Length);
                stubDesc.apfnExprEval = Marshal.AllocHGlobal(IntPtr.Size * exprEvalRoutines.Length);
                for (int i = 0; i < exprEvalRoutines.Length; i++)
                {
                    RpceStubExprEvalCallback callback = new RpceStubExprEvalCallback(this, exprEvalRoutines[i]);
                    NativeMethods.EXPR_EVAL  exprEval = new NativeMethods.EXPR_EVAL(callback.EXPR_EVAL);
                    IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(exprEval);
                    Marshal.WriteIntPtr(stubDesc.apfnExprEval, IntPtr.Size * i, funcPtr);

                    //http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getfunctionpointerfordelegate.aspx
                    //Caller must manually keep the delegate from being collected by
                    // the garbage collector from managed code.
                    exprEvalList.Add(exprEval);
                }
            }
            stubDesc.aXmitQuintuple = IntPtr.Zero;

            stubDesc.pFormatTypes = Marshal.AllocHGlobal(typeFormatString.Length);
            Marshal.Copy(typeFormatString, 0, stubDesc.pFormatTypes, typeFormatString.Length);

            stubDesc.fCheckBounds          = 0;         /* -error bounds_check flag : "midl /error none" */
            stubDesc.Version               = 0x50000;   /* Ndr library version */
            stubDesc.pMallocFreeStruct     = IntPtr.Zero;
            stubDesc.MIDLVersion           = 0x70001e6; /* MIDL Version 7.0.486 */
            stubDesc.CommFaultOffsets      = IntPtr.Zero;
            stubDesc.aUserMarshalQuadruple = IntPtr.Zero;
            stubDesc.NotifyRoutineTable    = IntPtr.Zero; /* notify & notify_flag routine table */
            stubDesc.mFlags          = 0x1;               /* MIDL flag */
            stubDesc.CsRoutineTables = IntPtr.Zero;       /* cs routines */
            stubDesc.ProxyServerInfo = IntPtr.Zero;       /* proxy/server native */
            stubDesc.pExprInfo       = IntPtr.Zero;       /* Reserved5 */

            #endregion
        }