/// <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]));
        }
Пример #2
0
        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());
        }
        /// <summary>
        /// Parse procedure header a from byte array to structure.
        /// </summary>
        /// <param name="procFormatString">Proc format string.</param>
        /// <param name="offset">Offset of a procedure in procFormatString.</param>
        /// <returns>The RpceProcedureHeaderDescriptor.</returns>
        public static RpceProcedureHeaderDescriptor ParseProcedureHeaderDescriptor(
            byte[] procFormatString,
            ref int offset)
        {
            //handle_type<1>
            //Oi_flags<1>
            //[rpc_flags<4>]
            //proc_num<2>
            //stack_size<2>
            //[explicit_handle_description<>]
            //constant_client_buffer_size<2>
            //constant_server_buffer_size<2>
            //INTERPRETER_OPT_FLAGS<1>
            //number_of_params<1>
            //extension_size<1>
            //[extension]

            const byte FC_BIND_PRIMITIVE       = 0x32;
            const int  PRIMITIVE_HANDLE_LENGTH = 4;
            const int  OTHER_HANDLE_LENGTH     = 6;
            const byte OI_HAS_RPCFLAGS         = 0x08;
            const int  EXTENSION_SIZE          = 8;

            RpceProcedureHeaderDescriptor procHeaderDesc = new RpceProcedureHeaderDescriptor();

            procHeaderDesc.HandleType = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.HandleType);
            procHeaderDesc.OiFlags = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.OiFlags);
            if ((procHeaderDesc.OiFlags & OI_HAS_RPCFLAGS) != 0)
            {
                procHeaderDesc.RpcFlags = BitConverter.ToUInt32(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.RpcFlags.Value);
            }
            procHeaderDesc.ProcNum = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ProcNum);
            procHeaderDesc.StackSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.StackSize);
            if (procHeaderDesc.HandleType == 0) // explicit handle
            {
                int length = (procFormatString[offset] == FC_BIND_PRIMITIVE)
                    ? PRIMITIVE_HANDLE_LENGTH
                    : OTHER_HANDLE_LENGTH;
                procHeaderDesc.ExplicitHandleDescription = ArrayUtility.SubArray(procFormatString, offset, length);
                offset += length;
            }
            procHeaderDesc.ClientBufferSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ClientBufferSize);
            procHeaderDesc.ServerBufferSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ServerBufferSize);
            procHeaderDesc.InterpreterOptFlags = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.InterpreterOptFlags);
            procHeaderDesc.NumberOfParams = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.NumberOfParams);
            byte extensionSize = procFormatString[offset];

            if (extensionSize >= EXTENSION_SIZE)
            {
                procHeaderDesc.ExtensionSize = extensionSize;
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionSize.Value);
                procHeaderDesc.ExtensionFlags2 = (RpceInterpreterOptFlags2)procFormatString[offset];
                offset += Marshal.SizeOf((byte)procHeaderDesc.ExtensionFlags2);
                procHeaderDesc.ExtensionClientCorrHint = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionClientCorrHint.Value);
                procHeaderDesc.ExtensionServerCorrHint = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionServerCorrHint.Value);
                procHeaderDesc.ExtensionNotifyIndex = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionNotifyIndex.Value);
                offset += extensionSize - EXTENSION_SIZE;
            }
            else
            {
                offset += extensionSize;
            }

            return(procHeaderDesc);
        }
        /// <summary>
        /// Parse procedure header a from byte array to structure.
        /// </summary>
        /// <param name="procFormatString">Proc format string.</param>
        /// <param name="offset">Offset of a procedure in procFormatString.</param>
        /// <returns>The RpceProcedureHeaderDescriptor.</returns>
        public static RpceProcedureHeaderDescriptor ParseProcedureHeaderDescriptor(
            byte[] procFormatString,
            ref int offset)
        {
            //handle_type<1>
            //Oi_flags<1>
            //[rpc_flags<4>]
            //proc_num<2>
            //stack_size<2>
            //[explicit_handle_description<>]
            //constant_client_buffer_size<2>
            //constant_server_buffer_size<2>
            //INTERPRETER_OPT_FLAGS<1>
            //number_of_params<1>
            //extension_size<1>
            //[extension]

            const byte FC_BIND_PRIMITIVE = 0x32;
            const int PRIMITIVE_HANDLE_LENGTH = 4;
            const int OTHER_HANDLE_LENGTH = 6;
            const byte OI_HAS_RPCFLAGS = 0x08;
            const int EXTENSION_SIZE = 8;

            RpceProcedureHeaderDescriptor procHeaderDesc = new RpceProcedureHeaderDescriptor();

            procHeaderDesc.HandleType = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.HandleType);
            procHeaderDesc.OiFlags = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.OiFlags);
            if ((procHeaderDesc.OiFlags & OI_HAS_RPCFLAGS) != 0)
            {
                procHeaderDesc.RpcFlags = BitConverter.ToUInt32(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.RpcFlags.Value);
            }
            procHeaderDesc.ProcNum = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ProcNum);
            procHeaderDesc.StackSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.StackSize);
            if (procHeaderDesc.HandleType == 0) // explicit handle
            {
                int length = (procFormatString[offset] == FC_BIND_PRIMITIVE)
                    ? PRIMITIVE_HANDLE_LENGTH
                    : OTHER_HANDLE_LENGTH;
                procHeaderDesc.ExplicitHandleDescription = ArrayUtility.SubArray(procFormatString, offset, length);
                offset += length;
            }
            procHeaderDesc.ClientBufferSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ClientBufferSize);
            procHeaderDesc.ServerBufferSize = BitConverter.ToUInt16(procFormatString, offset);
            offset += Marshal.SizeOf(procHeaderDesc.ServerBufferSize);
            procHeaderDesc.InterpreterOptFlags = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.InterpreterOptFlags);
            procHeaderDesc.NumberOfParams = procFormatString[offset];
            offset += Marshal.SizeOf(procHeaderDesc.NumberOfParams);
            byte extensionSize = procFormatString[offset];
            if (extensionSize >= EXTENSION_SIZE)
            {
                procHeaderDesc.ExtensionSize = extensionSize;
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionSize.Value);
                procHeaderDesc.ExtensionFlags2 = (RpceInterpreterOptFlags2)procFormatString[offset];
                offset += Marshal.SizeOf((byte)procHeaderDesc.ExtensionFlags2);
                procHeaderDesc.ExtensionClientCorrHint = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionClientCorrHint.Value);
                procHeaderDesc.ExtensionServerCorrHint = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionServerCorrHint.Value);
                procHeaderDesc.ExtensionNotifyIndex = BitConverter.ToUInt16(procFormatString, offset);
                offset += Marshal.SizeOf(procHeaderDesc.ExtensionNotifyIndex.Value);
                offset += extensionSize - EXTENSION_SIZE;
            }
            else
            {
                offset += extensionSize;
            }

            return procHeaderDesc;
        }