/// <summary>
 /// Returns the size (in bytes) of the given message value.
 /// </summary>
 /// <param name="value">The value which size is to be calculated.</param>
 /// <returns>The size (in bytes) of the given value</returns>
 public int GetSize(object value)
 {
     lock (messageUtilsLock)
     {
         return(marshaler.GetSize(value));
     }
 }
        public static T[] ToArray <T>(IntPtr ptr, int size) where T : struct
        {
            if (ptr == IntPtr.Zero)
            {
                return(null);
            }
            if (size == 0)
            {
                return(new T[0]);
            }

            MarshalingDescriptor marshalDesc;
            Marshaler            marshaller = CreateNativeMarshaller(
                typeof(T[]),
                null,
                size,
                null,
                false,
                -1,
                out marshalDesc);

            int     arraySize = marshaller.GetSize(marshalDesc, null);
            IRegion region    = marshaller.MakeRegion(ptr, arraySize);

            return((T[])marshaller.UnmarshalFrom(marshalDesc, region));
        }
        /// <summary>
        /// Marshal a managed array to unmanaged memory.
        /// </summary>
        /// <typeparam name="T">Type of elements in the array.</typeparam>
        /// <param name="array">An array to marshal.</param>
        /// <returns>Marshalled unmanaged memory.</returns>
        public static SafeIntPtr ToIntPtr <T>(T[] array) where T : struct
        {
            if (array == null)
            {
                return(IntPtr.Zero);
            }

            MarshalingDescriptor marshalDesc;
            Marshaler            marshaller = CreateNativeMarshaller(
                typeof(T[]),
                null,
                array.Length,
                null,
                false,
                -1,
                out marshalDesc);

            int    size = marshaller.GetSize(marshalDesc, array);
            IntPtr ptr  = Marshal.AllocHGlobal(size);

            IRegion region = marshaller.MakeRegion(ptr, size);

            marshaller.MarshalInto(marshalDesc, region, array);

            return(new TypeMarshalSafeIntPtr(marshaller, ptr));
        }
        /// <summary>
        /// Marshal a managed structure to unmanaged memory.
        /// </summary>
        /// <typeparam name="T">Type of struct.</typeparam>
        /// <param name="t">A structure to marshal.</param>
        /// <param name="switchValue">Switch attribute value if presents.</param>
        /// <param name="sizeValue">Size attribute value if presents.</param>
        /// <param name="lengthValue">Length attribute value if presents.</param>
        /// <returns>Marshalled unmanaged memory.</returns>
        public static SafeIntPtr ToIntPtr <T>(
            T t,
            object switchValue,
            object sizeValue,
            object lengthValue) where T : struct
        {
            MarshalingDescriptor marshalDesc;
            Marshaler            marshaller = CreateNativeMarshaller(
                typeof(T),
                switchValue,
                sizeValue,
                lengthValue,
                false,
                -1,
                out marshalDesc);

            int    size = marshaller.GetSize(marshalDesc, t);
            IntPtr ptr  = Marshal.AllocHGlobal(size);

            IRegion region = marshaller.MakeRegion(ptr, size);

            marshaller.MarshalInto(marshalDesc, region, t);

            return(new TypeMarshalSafeIntPtr(marshaller, ptr));
        }
        public static int GetNativeMemorySize <T>(
            object switchValue,
            object sizeValue,
            object lengthValue,
            bool force32Bit,
            int align) where T : struct
        {
            MarshalingDescriptor marshalDesc;
            Marshaler            marshaller = CreateNativeMarshaller(
                typeof(T),
                switchValue,
                sizeValue,
                lengthValue,
                force32Bit,
                align,
                out marshalDesc);

            return(marshaller.GetSize(marshalDesc, null));
        }
        public static T ToStruct <T>(
            IntPtr ptr,
            object switchValue,
            object sizeValue,
            object lengthValue,
            bool force32Bit = false,
            int align       = -1) where T : struct
        {
            MarshalingDescriptor marshalDesc;
            Marshaler            marshaller = CreateNativeMarshaller(
                typeof(T),
                switchValue,
                sizeValue,
                lengthValue,
                force32Bit,
                align,
                out marshalDesc);

            int     size   = marshaller.GetSize(marshalDesc, null);
            IRegion region = marshaller.MakeRegion(ptr, size);

            return((T)marshaller.UnmarshalFrom(marshalDesc, region));
        }
            internal void AllocateMemoryRegion(Marshaler marshaler, object value)
            {
                if (marshallingRegion != null)
                {
                    marshaler.MarkMemoryForDispose(this.marshallingRegion.NativeMemory);
                    this.marshallingRegion = null;
                }

                if (context.Type != typeof(void))
                {
                    int s = marshaler.GetSize(context, value);
                    IntPtr p = Marshal.AllocHGlobal(s);
                    this.marshallingRegion = marshaler.MakeRegion(p, s);
                }
                else
                    this.marshallingRegion = null;
            }
        protected override IMessage Invoke(IMethodCallMessage mcall)
        {
            Marshaler marshaler = new Marshaler(site, NativeMarshalingConfiguration.Configuration);

            foreach (Type type in proxiedType.Assembly.GetTypes())
            {
                marshaler.DefineCustomType(type.Name, type);
            }

            if (mcall.MethodBase == getHandleMethod)
                return GetHandle(mcall);
            if (mcall.MethodBase == setHandleMethod)
                return SetHandle(mcall);

            Initialize();

            RpcStub stub;
            if (!stubs.TryGetValue(mcall.MethodBase, out stub))
                throw new InvalidOperationException(String.Format("cannot find stub for method '{0}'", mcall.MethodBase));

            // marshal parameters
            int n = stub.parameters.Length;
            int actualsOffs = handleImplicit ? 1 : 0;
            object[] actuals = new object[n + actualsOffs];
            if (handleImplicit)
            {
                if (handle == null)
                    marshaler.TestAssumeFail(
                        "handle undefined for rpc interface '{0}' with implicit handle passing",
                        proxiedType);
                IntPtr ptr = Marshal.StringToHGlobalUni(handle);
                marshaler.MarkMemoryForDispose(ptr);
                actuals[0] = ptr;
            }
            marshaler.EnterContext();
            for (int i = 0; i < n; i++)
            {
                if (!stub.parameters[i].IsOut)
                {
                    marshaler.DefineSymbol(mcall.GetArgName(i), mcall.Args[i]);
                }
            }

            ParameterInfo[] parameterInfos = mcall.MethodBase.GetParameters();
            for (int pass = 0; pass < 2; pass++)
            {
                for (int i = 0; i < n; i++)
                {
                    if (pass == 0 && stub.parameters[i].HasDynamicExpression)
                    {
                        continue;
                    }

                    if (pass == 1
                        && !stub.parameters[i].HasDynamicExpression)
                    {
                        continue;
                    }

                    stub.parameters[i].AllocateMemoryRegion(marshaler, mcall.Args[i]);

                    RpcParameter rp = stub.parameters[i];
                    if (rp.marshallingRegion != null)
                        rp.marshallingRegion.TryReset();
                    if (!rp.IsOut
                        && mcall.Args[i] != null)
                    {
                        object value = mcall.Args[i];

                        // Validate the value of the parameter.
                        if (this.needAutoValidate)
                            CheckParameter(parameterInfos[i], value, mcall, marshaler.SymbolStore);

                        marshaler.MarshalInto(rp.context, rp.marshallingRegion, mcall.Args[i]);
                    }
                    else
                    {
                        marshaler.EnterRegion(rp.marshallingRegion);
                        marshaler.Clear(marshaler.GetSize(rp.context, null));
                        marshaler.ExitRegion();
                    }
                    if (!rp.IsByRef)
                    {
                        actuals[i + actualsOffs] = rp.Get();
                    }
                    else
                    {
                        if (mcall.Args[i] == null && !rp.IsOut)
                        {
                            actuals[i + actualsOffs] = IntPtr.Zero;
                        }
                        else
                        {
                            actuals[i + actualsOffs] = rp.marshallingRegion.NativeMemory;
                        }
                    }

                    marshaler.DefineSymbol(mcall.GetArgName(i), actuals[i + actualsOffs]);
                }
            }

            // call
            object result;
            try
            {
                result = stub.stubMethod.Invoke(null, actuals);
            }
            catch (TargetInvocationException e)
            {
                throw e.InnerException;
            }

            // marshal output parameters
            object[] resultArgs = new object[n];

            marshaler.IsProbingUnmarshaling = true;
            for (int pass = 0; pass < 2; pass++)
            {
                for (int i = 0; i < n; i++)
                {
                    RpcParameter rp = stub.parameters[i];

                    if (rp.marshallingRegion != null)
                        rp.marshallingRegion.TryReset();
                    if (rp.IsByRef)
                    {
                        object res = resultArgs[i] =
                            marshaler.UnmarshalFrom(rp.context, rp.marshallingRegion);

                        if (marshaler.IsProbingUnmarshaling == false)
                        {
                            RpcAdapterValidate(res, rp.context.Attributes, marshaler.SymbolStore);

                            if (rp.IsOut && marshaler.GetNativeType(rp.context) == typeof(IntPtr))
                            {
                                foreach (IntPtr ptr in marshaler.ForeignMemory)
                                {
                                    if (ptr != IntPtr.Zero && rpcFreeMethod != null)
                                    {
                                        rpcFreeMethod.Invoke(null, new object[] { ptr });
                                    }
                                }
                            }
                        }
                        marshaler.ForeignMemory.Clear();
                        if (!rp.IsByRef)
                        {
                            marshaler.DefineSymbol(mcall.GetArgName(i), rp.Get());
                        }
                        else
                        {
                            marshaler.DefineSymbol(mcall.GetArgName(i),
                                rp.marshallingRegion.NativeMemory);
                        }
                    }
                    else
                    {
                        resultArgs[i] = mcall.Args[i];
                    }
                }
                marshaler.IsProbingUnmarshaling = false;
            }
            if (stub.returnParameter.nativeType != typeof(void))
            {
                stub.returnParameter.AllocateMemoryRegion(marshaler, result);

                stub.returnParameter.marshallingRegion.TryReset();
                stub.returnParameter.Set(result);
                result = marshaler.UnmarshalFrom(
                            stub.returnParameter.context,
                            stub.returnParameter.marshallingRegion);

                RpcAdapterValidate(result, null, null);
            }
            marshaler.ExitContext();
            marshaler.FreeMemory();
            marshaler.Dispose();
            marshaler = null;

            CheckOperation(mcall);
            ReturnMessage mret = new ReturnMessage(result, resultArgs, resultArgs.Length, mcall.LogicalCallContext, mcall);
            return mret;
        }