/// <summary>
        /// Decode byte array to parameter list in one method call.
        /// Calling this method assumes that decoding the stub doesn't depends on any parameter.
        /// Only for decoding the stub data from the client side.
        /// </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>
        /// <param name="procFormatString">Proc format string generated by MIDL.</param>
        /// <param name="procFormatStringOffset">Offset of the procedure in procFormatString.</param>
        /// <param name="isClient">Is client side.</param>
        /// <param name="bytesToDecode">Bytes to decode.</param>
        /// <returns>The decoded parameter list.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when typeFormatString is null.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown when runtimeTargetPlatform doesn't match current platform at runtime.
        /// </exception>
        public static RpceInt3264Collection ToParamList(
            RpceStubTargetPlatform runtimeTargetPlatform,
            byte[] typeFormatString,
            RpceStubExprEval[] exprEvalRoutines,
            byte[] procFormatString,
            int procFormatStringOffset,
            bool isClient,
            byte[] bytesToDecode)
        {
            int offset = procFormatStringOffset;
            RpceProcedureHeaderDescriptor procHeaderInfo
                = RpceStubHelper.ParseProcedureHeaderDescriptor(procFormatString, ref offset);

            return(ToParamList(runtimeTargetPlatform, typeFormatString, exprEvalRoutines, procFormatString,
                               procFormatStringOffset, isClient, bytesToDecode, new Int3264[procHeaderInfo.NumberOfParams]));
        }
        private Int3264[] NdrParametersUnmarshall(
            byte[] procFormatString,
            int offset,
            bool isClient,
            params Int3264[] parameters)
        {
            if (procFormatString == null)
            {
                throw new ArgumentNullException("procFormatString");
            }

            RpceProcedureHeaderDescriptor procHeaderInfo
                = RpceStubHelper.ParseProcedureHeaderDescriptor(procFormatString, ref offset);

            if (procHeaderInfo.NumberOfParams != parameters.Length)
            {
                throw new InvalidOperationException("Number of parameters doesn't match expectation.");
            }

            SaveParametersIntoStack(procFormatString, offset, procHeaderInfo.StackSize, parameters);

            if ((procHeaderInfo.ExtensionFlags2 & RpceInterpreterOptFlags2.HasConformanceRange) != 0)
            {
                SetCorrDespIncrement(RANGED_NDR_CORR_EXTENSION_SIZE);
            }
            else
            {
                SetCorrDespIncrement(NDR_CORR_EXTENSION_SIZE);
            }

            NdrConvertIfNecessary(procFormatString, offset, procHeaderInfo.NumberOfParams, isClient);

            List <Int3264> parameterList = new List <Int3264>(parameters);

            for (int i = 0; i < procHeaderInfo.NumberOfParams; i++)
            {
                RpceParameterAttributes parameterFlags = (RpceParameterAttributes)BitConverter.ToUInt16(procFormatString, offset);
                offset += sizeof(RpceParameterAttributes);
                offset += sizeof(ushort); //skip stack size/top
                ushort parameterTypeFormatStringOffset = BitConverter.ToUInt16(procFormatString, offset);
                offset += sizeof(ushort); //move to next parameter.

                bool sameDirection = (isClient
                    ? (parameterFlags & RpceParameterAttributes.IsOut)
                    : (parameterFlags & RpceParameterAttributes.IsIn)) != 0;
                if (!sameDirection)
                {
                    continue;
                }
                if ((parameterFlags & RpceParameterAttributes.IsPipe) != 0)
                {
                    continue;
                }
                if (!isClient && (parameterFlags & RpceParameterAttributes.IsPartialIgnore) != 0)
                {
                    parameterList[i] = NdrInt32Unmarshal() != 0 ? 1 : 0;
                    continue;
                }

                RpceFormatCharType formatChar;
                if ((parameterFlags & RpceParameterAttributes.IsBaseType) != 0)
                {
                    formatChar = (RpceFormatCharType)parameterTypeFormatStringOffset;
                }
                else
                {
                    formatChar = (RpceFormatCharType)Marshal.ReadByte(
                        stubDesc.pFormatTypes,
                        parameterTypeFormatStringOffset);
                }

                parameterList[i] = NdrUnmarshalRoutines(parameters[i], parameterTypeFormatStringOffset, formatChar);


                if ((parameterFlags & RpceParameterAttributes.IsBaseType) != 0 &&
                    (parameterFlags & RpceParameterAttributes.IsSimpleRef) != 0)
                {
                    IntPtr ptr = Marshal.AllocHGlobal(sizeof(ulong));//ulong is max size of simple type.
                    FreeMemoryAtDispose(ptr);
                    Marshal.WriteIntPtr(ptr, parameterList[i]);
                    parameterList[i] = ptr;
                }
            }

            return(parameterList.ToArray());
        }