public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod)
        {
            Debug.Assert(targetMethod.IsPInvoke);

            MarshalDirection direction = MarshalDirection.Forward;
            MethodSignature  methodSig = targetMethod.Signature;
            PInvokeFlags     flags     = targetMethod.GetPInvokeMethodMetadata().Flags;

            ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata();
            Marshaller[]        marshallers            = new Marshaller[methodSig.Length + 1];
            ParameterMetadata   parameterMetadata;

            for (int i = 0, parameterIndex = 0; i < marshallers.Length; i++)
            {
                Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index);
                if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index)
                {
                    // if we don't have metadata for the parameter, create a dummy one
                    parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null);
                }
                else
                {
                    Debug.Assert(i == parameterMetadataArray[parameterIndex].Index);
                    parameterMetadata = parameterMetadataArray[parameterIndex++];
                }

                TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1];  //first item is the return type
                marshallers[i] = CreateMarshaller(parameterType,
                                                  parameterIndex,
                                                  methodSig.GetEmbeddedSignatureData(),
                                                  MarshallerType.Argument,
                                                  parameterMetadata.MarshalAsDescriptor,
                                                  direction,
                                                  marshallers,
                                                  parameterMetadata.Index,
                                                  flags,
                                                  parameterMetadata.In,
                                                  parameterMetadata.Out,
                                                  parameterMetadata.Return);
            }

            return(marshallers);
        }
Example #2
0
        private Marshaller[] InitializeMarshallers()
        {
            Debug.Assert(_interopStateManager != null);
            MarshalAsDescriptor[] marshalAsDescriptors = ((MetadataType)ManagedType).GetFieldMarshalAsDescriptors();
            Marshaller[]          marshallers          = new Marshaller[marshalAsDescriptors.Length];

            PInvokeFlags flags = new PInvokeFlags();

            if (ManagedType.PInvokeStringFormat == PInvokeStringFormat.UnicodeClass || ManagedType.PInvokeStringFormat == PInvokeStringFormat.AutoClass)
            {
                flags.CharSet = CharSet.Unicode;
            }
            else
            {
                flags.CharSet = CharSet.Ansi;
            }

            int index = 0;

            foreach (FieldDesc field in ManagedType.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                marshallers[index] = Marshaller.CreateMarshaller(field.FieldType,
                                                                 MarshallerType.Field,
                                                                 marshalAsDescriptors[index],
                                                                 (ThunkType == StructMarshallingThunkType.NativeToManaged) ? MarshalDirection.Reverse : MarshalDirection.Forward,
                                                                 marshallers,
                                                                 _interopStateManager,
                                                                 index,
                                                                 flags,
                                                                 isIn: true,        /* Struct fields are considered as IN within the helper*/
                                                                 isOut: false,
                                                                 isReturn: false);
                index++;
            }

            return(marshallers);
        }
Example #3
0
        public static bool IsMarshallingRequired(MethodDesc targetMethod)
        {
            Debug.Assert(targetMethod.IsPInvoke);

            if (targetMethod.IsUnmanagedCallersOnly)
            {
                return(true);
            }

            PInvokeMetadata metadata = targetMethod.GetPInvokeMethodMetadata();
            PInvokeFlags    flags    = metadata.Flags;

            if (flags.SetLastError)
            {
                return(true);
            }

            if (!flags.PreserveSig)
            {
                return(true);
            }

            if (MarshalHelpers.ShouldCheckForPendingException(targetMethod.Context.Target, metadata))
            {
                return(true);
            }

            var marshallers = GetMarshallersForMethod(targetMethod);

            for (int i = 0; i < marshallers.Length; i++)
            {
                if (marshallers[i].IsMarshallingRequired())
                {
                    return(true);
                }
            }

            return(false);
        }
Example #4
0
        private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager)
        {
            Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk || targetMethod is CalliMarshallingMethodThunk);
            _targetMethod = targetMethod;
            _pInvokeILEmitterConfiguration = pinvokeILEmitterConfiguration;
            _pInvokeMetadata     = targetMethod.GetPInvokeMethodMetadata();
            _interopStateManager = interopStateManager;

            //
            // targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk
            // ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is
            // important to check them first here so that we get the right flags.
            //
            if (_targetMethod is DelegateMarshallingMethodThunk delegateMethod)
            {
                _flags = ((EcmaType)delegateMethod.DelegateType.GetTypeDefinition()).GetDelegatePInvokeFlags();
            }
            else
            {
                _flags = _pInvokeMetadata.Flags;
            }
            _marshallers = InitializeMarshallers(targetMethod, interopStateManager, _flags);
        }
Example #5
0
        public static PInvokeFlags GetDelegatePInvokeFlags(this EcmaType type)
        {
            PInvokeFlags flags = new PInvokeFlags(PInvokeAttributes.PreserveSig);

            if (!type.IsDelegate)
            {
                return(flags);
            }

            var customAttributeValue = type.GetDecodedCustomAttribute(
                "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");

            if (customAttributeValue == null)
            {
                return(flags);
            }

            if (!customAttributeValue.HasValue)
            {
                return(flags);
            }

            if (customAttributeValue.Value.FixedArguments.Length == 1)
            {
                CallingConvention callingConvention = (CallingConvention)customAttributeValue.Value.FixedArguments[0].Value;

                switch (callingConvention)
                {
                case CallingConvention.StdCall:
                    flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionStdCall;
                    break;

                case CallingConvention.Cdecl:
                    flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionCdecl;
                    break;

                case CallingConvention.ThisCall:
                    flags.UnmanagedCallingConvention = MethodSignatureFlags.UnmanagedCallingConventionThisCall;
                    break;

                case CallingConvention.Winapi:
                    // Platform default
                    break;
                }
            }

            foreach (var namedArgument in customAttributeValue.Value.NamedArguments)
            {
                if (namedArgument.Name == "CharSet")
                {
                    flags.CharSet = (CharSet)namedArgument.Value;
                }
                else if (namedArgument.Name == "BestFitMapping")
                {
                    flags.BestFitMapping = (bool)namedArgument.Value;
                }
                else if (namedArgument.Name == "SetLastError")
                {
                    flags.SetLastError = (bool)namedArgument.Value;
                }
                else if (namedArgument.Name == "ThrowOnUnmappableChar")
                {
                    flags.ThrowOnUnmappableChar = (bool)namedArgument.Value;
                }
            }
            return(flags);
        }
Example #6
0
        private static                                 Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags)
        {
            bool             isDelegate = targetMethod is DelegateMarshallingMethodThunk;
            MethodSignature  methodSig  = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).DelegateSignature : targetMethod.Signature;
            MarshalDirection direction  = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).Direction: MarshalDirection.Forward;
            int indexOffset             = 0;

            if (!methodSig.IsStatic && direction == MarshalDirection.Forward)
            {
                // For instance methods(eg. Forward delegate marshalling thunk), first argument is
                // the instance
                indexOffset = 1;
            }
            ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata();
            Marshaller[]        marshallers            = new Marshaller[methodSig.Length + 1];
            int parameterIndex = 0;
            ParameterMetadata parameterMetadata;

            for (int i = 0; i < marshallers.Length; i++)
            {
                Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index);
                if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index)
                {
                    // if we don't have metadata for the parameter, create a dummy one
                    parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null);
                }
                else
                {
                    Debug.Assert(i == parameterMetadataArray[parameterIndex].Index);
                    parameterMetadata = parameterMetadataArray[parameterIndex++];
                }
                TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1];  //first item is the return type
                marshallers[i] = Marshaller.CreateMarshaller(parameterType,
                                                             MarshallerType.Argument,
                                                             parameterMetadata.MarshalAsDescriptor,
                                                             direction,
                                                             marshallers,
                                                             interopStateManager,
                                                             indexOffset + parameterMetadata.Index,
                                                             flags,
                                                             parameterMetadata.In,
                                                             parameterMetadata.Out,
                                                             parameterMetadata.Return
                                                             );
            }

            return(marshallers);
        }
Example #7
0
        private static                                 Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags)
        {
            MarshalDirection direction = MarshalDirection.Forward;
            MethodSignature  methodSig;

            switch (targetMethod)
            {
            case DelegateMarshallingMethodThunk delegateMethod:
                methodSig = delegateMethod.DelegateSignature;
                direction = delegateMethod.Direction;
                break;

            case CalliMarshallingMethodThunk calliMethod:
                methodSig = calliMethod.TargetSignature;
                break;

            default:
                methodSig = targetMethod.Signature;
                break;
            }
            int indexOffset = 0;

            if (!methodSig.IsStatic && direction == MarshalDirection.Forward)
            {
                // For instance methods(eg. Forward delegate marshalling thunk), first argument is
                // the instance
                indexOffset = 1;
            }
            ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata();
            Marshaller[]        marshallers            = new Marshaller[methodSig.Length + 1];
            int parameterIndex = 0;
            ParameterMetadata parameterMetadata;

            for (int i = 0; i < marshallers.Length; i++)
            {
                Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index);
                if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index)
                {
                    // if we don't have metadata for the parameter, create a dummy one
                    parameterMetadata = new ParameterMetadata(i, ParameterMetadataAttributes.None, null);
                }
                else
                {
                    Debug.Assert(i == parameterMetadataArray[parameterIndex].Index);
                    parameterMetadata = parameterMetadataArray[parameterIndex++];
                }

                TypeDesc parameterType;
                bool     isHRSwappedRetVal = false;
                if (i == 0)
                {
                    // First item is the return type
                    parameterType = methodSig.ReturnType;
                    if (!flags.PreserveSig && !parameterType.IsVoid)
                    {
                        // PreserveSig = false can only show up an regular forward PInvokes
                        Debug.Assert(direction == MarshalDirection.Forward);

                        parameterType     = methodSig.Context.GetByRefType(parameterType);
                        isHRSwappedRetVal = true;
                    }
                }
                else
                {
                    parameterType = methodSig[i - 1];
                }

                marshallers[i] = Marshaller.CreateMarshaller(parameterType,
                                                             parameterIndex,
                                                             methodSig.GetEmbeddedSignatureData(),
                                                             MarshallerType.Argument,
                                                             parameterMetadata.MarshalAsDescriptor,
                                                             direction,
                                                             marshallers,
                                                             interopStateManager,
                                                             indexOffset + parameterMetadata.Index,
                                                             flags,
                                                             parameterMetadata.In,
                                                             isHRSwappedRetVal ? true : parameterMetadata.Out,
                                                             isHRSwappedRetVal ? false : parameterMetadata.Return
                                                             );
            }

            return(marshallers);
        }
Example #8
0
 public PInvokeMethodFixupNode PInvokeMethodFixup(string moduleName, string entryPointName, PInvokeFlags flags)
 {
     return(_pInvokeMethodFixups.GetOrAdd(Tuple.Create(moduleName, entryPointName, flags)));
 }
Example #9
0
 public PInvokeMethodFixupNode(string moduleName, string entryPointName, PInvokeFlags flags)
 {
     _moduleName     = moduleName;
     _entryPointName = entryPointName;
     _flags          = flags;
 }
Example #10
0
 public PInvokeMethodFixupNode(PInvokeModuleData moduleData, string entryPointName, PInvokeFlags flags)
 {
     _moduleData     = moduleData;
     _entryPointName = entryPointName;
     _flags          = flags;
 }
Example #11
0
        public override MethodIL EmitIL()
        {
            try
            {
                Debug.Assert(_interopStateManager != null);
                Marshaller[]          marshallers          = new Marshaller[GetNumberOfInstanceFields()];
                MarshalAsDescriptor[] marshalAsDescriptors = ((MetadataType)ManagedType).GetFieldMarshalAsDescriptors();

                PInvokeFlags flags = new PInvokeFlags();
                if (ManagedType.PInvokeStringFormat == PInvokeStringFormat.UnicodeClass || ManagedType.PInvokeStringFormat == PInvokeStringFormat.AutoClass)
                {
                    flags.CharSet = CharSet.Unicode;
                }
                else
                {
                    flags.CharSet = CharSet.Ansi;
                }


                int index = 0;

                foreach (FieldDesc field in ManagedType.GetFields())
                {
                    if (field.IsStatic)
                    {
                        continue;
                    }

                    marshallers[index] = Marshaller.CreateMarshaller(field.FieldType,
                                                                     MarshallerType.Field,
                                                                     marshalAsDescriptors[index],
                                                                     (ThunkType == StructMarshallingThunkType.NativeToManage) ? MarshalDirection.Reverse : MarshalDirection.Forward,
                                                                     marshallers,
                                                                     _interopStateManager,
                                                                     index,
                                                                     flags,
                                                                     isIn: true,        /* Struct fields are considered as IN within the helper*/
                                                                     isOut: false,
                                                                     isReturn: false);
                    index++;
                }

                PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams();

                if (ThunkType == StructMarshallingThunkType.Cleanup)
                {
                    return(EmitCleanupIL(pInvokeILCodeStreams, marshallers));
                }
                else
                {
                    return(EmitMarshallingIL(pInvokeILCodeStreams, marshallers));
                }
            }
            catch (NotSupportedException)
            {
                string message = "Struct '" + ((MetadataType)ManagedType).Name +
                                 "' requires non-trivial marshalling that is not yet supported by this compiler.";
                return(MarshalHelpers.EmitExceptionBody(message, this));
            }
            catch (InvalidProgramException ex)
            {
                Debug.Assert(!String.IsNullOrEmpty(ex.Message));
                return(MarshalHelpers.EmitExceptionBody(ex.Message, this));
            }
        }