コード例 #1
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public PrimitiveNativeType(NativeTypeDesc desc, UnmanagedType[] allowedUnmanagedTypes)
            : this(desc)
        {
            UnmanagedType unmng_type = ValidateUnmanagedType(desc, allowedUnmanagedTypes);

            if (desc.Type == typeof(bool))
            {
                // Boolean as I1 and I2 should print 'bool' as the plain C++ type
                if (unmng_type == UnmanagedType.I1)
                {
                    typeName = TypeName.I1_Bool;
                }
                if (unmng_type == UnmanagedType.U1)
                {
                    typeName = TypeName.U1_Bool;
                }
            }

            if (typeName.IsEmpty)
            {
                typeName = TypeName.GetTypeNameForUnmanagedType(unmng_type);
                Debug.Assert(!typeName.IsEmpty);
            }

            if (unmng_type == UnmanagedType.SysInt ||
                unmng_type == UnmanagedType.SysUInt)
            {
                // IntPtr and UIntPtr translate into "void *"
                indirections++;
            }
        }
コード例 #2
0
        public EnumNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type.IsEnum);

            Type underlying_type = Enum.GetUnderlyingType(desc.Type);

            // verify managed/unmanaged combination (enums are normalized to their underlying type)
            UnmanagedType underlying_unmanaged_type;

            UnmanagedType[] allowed_unmanaged_types = Utility.GetAllowedUnmanagedTypesForEnum(underlying_type);

            if (allowed_unmanaged_types != null)
            {
                // we want the potential validation error to go this type's log
                underlying_unmanaged_type = ValidateUnmanagedType(desc, allowed_unmanaged_types);
            }
            else
            {
                Log.Add(Errors.ERROR_UnexpectedEnumUnderlyingType, underlying_type.FullName);
                underlying_unmanaged_type = UnmanagedType.I4;
            }

            // pass the underlying native type to the definition
            this.typeDefinition = EnumDefinition.Get(desc, underlying_unmanaged_type);
            this.nameModifier   = String.Empty;
        }
コード例 #3
0
ファイル: Classes.cs プロジェクト: toiiggww/clrinterop
 /// <summary>
 /// Allows the interface name to be specified explicitly.
 /// </summary>
 public InterfaceNativeType(NativeTypeDesc desc, TypeName typeName)
     : base(desc)
 {
     this.typeName  = typeName;
     this.isVariant = false;
     this.indirections++;
 }
コード例 #4
0
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.ByValArray"/>.
        /// </summary>
        private void InitializeAsByValArray(NativeTypeDesc desc)
        {
            Debug.Assert(this.indirections == 0);

            this.arrayKind = ArrayKind.ByValArray;

            // const size must be specified and >0
            if (desc.MarshalAs == null || desc.MarshalAs.SizeConst <= 0)
            {
                Log.Add(Errors.ERROR_ByValArrayInvalidLength);
                this.length = 1;
            }
            else
            {
                // no need to output any INFO as this number will be between brackets in the code
                this.length = desc.MarshalAs.SizeConst;
            }

            UnmanagedType element_unmng_type =
                (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType);

            if (element_unmng_type == (UnmanagedType)80)
            {
                element_unmng_type = (UnmanagedType)0;
            }

            // determine the element type
            this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags);
        }
コード例 #5
0
ファイル: Strings.cs プロジェクト: dbremner/clrinterop
        public CharNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            UnmanagedType ut = ValidateUnmanagedType(desc, MarshalType.Char, UnmanagedType.AsAny);
            if (ut == UnmanagedType.AsAny)
            {
                // default marshaling
                if (desc.IsComInterop) ut = UnmanagedType.U2;
                else
                {
                    if (desc.AnsiStrings) ut = UnmanagedType.I1;
                    else if (desc.UnicodeStrings) ut = UnmanagedType.U2;
                    else
                    {
                        // "TCHAR"
                        this.typeName = (desc.AnsiPlatform ? TypeName.TCharA : TypeName.TCharW);

                        Log.Add(Errors.INFO_AutoCharacterMarshaling);
                        return;
                    }
                }
            }

            switch (ut)
            {
                case UnmanagedType.I1: this.typeName = TypeName.I1; break;
                case UnmanagedType.I2: this.typeName = TypeName.I2; break;
                case UnmanagedType.U1: this.typeName = TypeName.UChar; break;
                case UnmanagedType.U2: this.typeName = TypeName.WChar; break;

                default:
                    Debug.Fail(null); break;
            }
        }
コード例 #6
0
        public static NativeTypeDefinition Get(NativeTypeDesc desc)
        {
            // delegates are marshaled as _Delegate COM interface
            // UUID = FB6AB00F-5096-3AF8-A33D-D7885A5FA829

            return(NativeTypeDefinition.Get <DelegateInterfaceDefinition>(
                       new TypeDefKey(typeof(Delegate), (desc.Flags & MarshalFlags.TypeDefKeyFlags) | MarshalFlags.ComInterop)));
        }
コード例 #7
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public DateNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type == typeof(DateTime));

            ValidateUnmanagedType(desc, MarshalType.Struct);
            this.typeName = TypeName.Date;
        }
コード例 #8
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public DateNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type == typeof(DateTime));

            ValidateUnmanagedType(desc, MarshalType.Struct);
            this.typeName = TypeName.Date;
        }
コード例 #9
0
        public static NativeTypeDefinition Get(NativeTypeDesc desc)
        {
            // when a delegate is marshaled as an unmanaged function pointer, its
            // parameters and return type have P/Invoke's default marshaling behavior
            // regardless of whether the function pointer is passed to a static entry
            // point or to a COM member

            return(NativeTypeDefinition.Get <FunctionPtrDefinition>(
                       new TypeDefKey(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags) & ~MarshalFlags.ComInterop)));
        }
コード例 #10
0
ファイル: Classes.cs プロジェクト: toiiggww/clrinterop
 private static bool IsMarshaledManagedToNative(NativeTypeDesc desc)
 {
     if (desc.IsCallbackParam)
     {
         return(desc.IsRetValParam || desc.MarshalsOut);
     }
     else
     {
         return(desc.MarshalsIn || (!desc.MarshalsOut && !desc.IsRetValParam));
     }
 }
コード例 #11
0
 private static bool HasSizeConst(NativeTypeDesc desc)
 {
     // Warning: there is currently no way how we can distinguish between the case where SizeConst is
     // not specified and the case where SizeConst is specified and set to 0. This method should be
     // updated when the MarshalAsAttribute is improved to provide this information.
     if (desc.MarshalAs == null)
     {
         return(false);
     }
     return(desc.MarshalAs.SizeConst != 0);
 }
コード例 #12
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public VariableArgumentListNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type == typeof(System.ArgIterator));

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            // marshals as va_list
            this.typeName = TypeName.VaList;
        }
コード例 #13
0
ファイル: Structs.cs プロジェクト: ARLM-Keller/clr-interop
 private void WarnBlittableInOutMismatch(NativeTypeDesc desc)
 {
     // the argument will always be passed in-out
     if (desc.MarshalsIn && !desc.MarshalsOut)
     {
         Log.Add(Errors.WARN_LayoutBlittableMarkedIn, desc.Type.FullName);
     }
     else if (!desc.MarshalsIn && desc.MarshalsOut)
     {
         Log.Add(Errors.WARN_LayoutBlittableMarkedOut, desc.Type.FullName);
     }
 }
コード例 #14
0
ファイル: Structs.cs プロジェクト: ARLM-Keller/clr-interop
        public StructureNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc.Type.IsValueType || desc.IsStructField)
            {
                // the only allowed UnmanagedType is Struct
                ValidateUnmanagedType(desc, MarshalType.Struct);
            }
            else
            {
                // the only allowed UnmanagedType is LPStruct
                ValidateUnmanagedType(desc, MarshalType.Class);

                // if it's not byref, then it goes in-only by default
                if (++this.indirections == 1)
                {
                    byDefaultInOnly = true;
                }
            }

            if (desc.MarshalAs != null)
            {
                // warn against explicit MarshalAsAttribute on a normalized structure
                Type marshal_type = Utility.GetNormalizedType(desc.Type);
                if (marshal_type != desc.Type)
                {
                    Log.Add(Errors.WARN_NormalizedStructure, desc.Type.FullName, marshal_type.FullName);
                }
            }

            if (!Utility.HasLayout(desc.Type))
            {
                Log.Add(Errors.ERROR_TypeHasNoLayout, desc.Type.FullName);
            }

            StructureDefinition struct_def = StructureDefinition.Get(desc);

            if (this.indirections == 1 && desc.PointerIndirections == 0)
            {
                // either byval class or byref struct
                ExplainPinningOrCopying(desc, struct_def.IsBlittable);
            }
            else if (this.indirections == 2 && desc.PointerIndirections == 0)
            {
                // byref class - double indirected
                ExplainMemoryManagement(desc,
                                        struct_def.IsUnion ? Resources._Union : Resources._Structure);
            }

            this.typeDefinition = struct_def;
            this.nameModifier   = (struct_def.IsUnion ? UnionModifier : StructModifier);
        }
コード例 #15
0
ファイル: Callbacks.cs プロジェクト: dbremner/clrinterop
        public CallbackNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(typeof(Delegate).IsAssignableFrom(desc.Type));

            UnmanagedType[] allowed_unmanaged_types;
            if (desc.IsStructField)
            {
                // fields of delegate type can only marshal as function pointers
                allowed_unmanaged_types = MarshalType.DelegField;
            }
            else
            {
                // parameters of delegate type
                allowed_unmanaged_types = (desc.IsComInterop ? MarshalType.DelegC : MarshalType.DelegP);
            }

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
                case UnmanagedType.FunctionPtr:
                {
                    if (!desc.IsCallbackParam)
                    {
                        // the "number one" mistake when marshaling delegate to function ptr
                        Log.Add(Errors.INFO_BewarePrematureDelegateRelease);
                    }

                    this.typeDefinition = FunctionPtrDefinition.Get(desc);
                    break;
                }

                case UnmanagedType.Interface:
                {
                    this.name = DelegateInterfaceDefinition.InterfaceName;
                    this.nameModifier = StructModifier;

                    this.indirections++;

                    Log.Add(Errors.INFO_SeeMscorlibTlbForInterface, this.name);

                    this.typeDefinition = DelegateInterfaceDefinition.Get(desc);
                    break;
                }

                default:
                {
                    Debug.Fail(null);
                    goto case UnmanagedType.FunctionPtr;
                }
            }
        }
コード例 #16
0
        public CallbackNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(typeof(Delegate).IsAssignableFrom(desc.Type));

            UnmanagedType[] allowed_unmanaged_types;
            if (desc.IsStructField)
            {
                // fields of delegate type can only marshal as function pointers
                allowed_unmanaged_types = MarshalType.DelegField;
            }
            else
            {
                // parameters of delegate type
                allowed_unmanaged_types = (desc.IsComInterop ? MarshalType.DelegC : MarshalType.DelegP);
            }

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
            case UnmanagedType.FunctionPtr:
            {
                if (!desc.IsCallbackParam)
                {
                    // the "number one" mistake when marshaling delegate to function ptr
                    Log.Add(Errors.INFO_BewarePrematureDelegateRelease);
                }

                this.typeDefinition = FunctionPtrDefinition.Get(desc);
                break;
            }

            case UnmanagedType.Interface:
            {
                this.name         = DelegateInterfaceDefinition.InterfaceName;
                this.nameModifier = StructModifier;

                this.indirections++;

                Log.Add(Errors.INFO_SeeMscorlibTlbForInterface, this.name);

                this.typeDefinition = DelegateInterfaceDefinition.Get(desc);
                break;
            }

            default:
            {
                Debug.Fail(null);
                goto case UnmanagedType.FunctionPtr;
            }
            }
        }
コード例 #17
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public GuidNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type == typeof(System.Guid));

            if (ValidateUnmanagedType(desc, MarshalType.Guid) == UnmanagedType.LPStruct)
            {
                this.isLPStruct = true;
                this.indirections++;
            }

            // marshals as either GUID or PGUID
            this.typeName = TypeName.Guid;
        }
コード例 #18
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        protected PrimitiveNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            this.platform64bit = desc.IsPlatform64Bit;

            // count the total level of indirections
            this.indirections = desc.PointerIndirections;
            if (desc.IsByRefParam)
            {
                this.indirections++;
            }

            VerifyMarshalDirection(desc);
        }
コード例 #19
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public ColorNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type == typeof(System.Drawing.Color));

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            if (!desc.IsComInterop)
            {
                Log.Add(Errors.ERROR_MarshalingAllowedForCom, desc.Type.FullName);
            }

            // marshals as OLE_COLOR
            this.typeName = TypeName.OleColor;
        }
コード例 #20
0
        public CharNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            UnmanagedType ut = ValidateUnmanagedType(desc, MarshalType.Char, UnmanagedType.AsAny);

            if (ut == UnmanagedType.AsAny)
            {
                // default marshaling
                if (desc.IsComInterop)
                {
                    ut = UnmanagedType.U2;
                }
                else
                {
                    if (desc.AnsiStrings)
                    {
                        ut = UnmanagedType.I1;
                    }
                    else if (desc.UnicodeStrings)
                    {
                        ut = UnmanagedType.U2;
                    }
                    else
                    {
                        // "TCHAR"
                        this.typeName = (desc.AnsiPlatform ? TypeName.TCharA : TypeName.TCharW);

                        Log.Add(Errors.INFO_AutoCharacterMarshaling);
                        return;
                    }
                }
            }

            switch (ut)
            {
            case UnmanagedType.I1: this.typeName = TypeName.I1; break;

            case UnmanagedType.I2: this.typeName = TypeName.I2; break;

            case UnmanagedType.U1: this.typeName = TypeName.UChar; break;

            case UnmanagedType.U2: this.typeName = TypeName.WChar; break;

            default:
                Debug.Fail(null); break;
            }
        }
コード例 #21
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public ColorNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type == typeof(System.Drawing.Color));

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            if (!desc.IsComInterop)
            {
                Log.Add(Errors.ERROR_MarshalingAllowedForCom, desc.Type.FullName);
            }

            // marshals as OLE_COLOR
            this.typeName = TypeName.OleColor;
        }
コード例 #22
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public HandleNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(
                desc.Type == typeof(System.Runtime.InteropServices.HandleRef) ||
                typeof(System.Runtime.InteropServices.SafeHandle).IsAssignableFrom(desc.Type) ||
                typeof(System.Runtime.InteropServices.CriticalHandle).IsAssignableFrom(desc.Type));

            if (desc.IsArrayElement && desc.Type != typeof(System.Runtime.InteropServices.HandleRef))
            {
                Log.Add(Errors.ERROR_HandlesNotPermittedAsArrayElements);
            }

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            // marshals as HANDLE
            this.typeName = TypeName.Handle;
        }
コード例 #23
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public DecimalNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type == typeof(Decimal));

            UnmanagedType[] allowed_unmanaged_types =
                (desc.IsStructField ? MarshalType.DecimalField : MarshalType.DecimalParam);

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
                case UnmanagedType.Currency:
                {
                    // marshals as CURRENCY COM type
                    this.typeName = TypeName.Currency;
                    break;
                }

                case UnmanagedType.Struct:
                {
                    // marshals as DECIMAL 96-bit type
                    this.typeName = TypeName.Decimal;
                    break;
                }

                case UnmanagedType.LPStruct:
                {
                    // marshals as a pointer to the DECIMAL 96-bit type
                    this.isLPStruct = true;
                    this.typeName = TypeName.Decimal;
                    this.indirections++;
                    break;
                }

                default:
                {
                    Debug.Fail(null);
                    break;
                }
            }
        }
コード例 #24
0
ファイル: Primitives.cs プロジェクト: toiiggww/clrinterop
        public DecimalNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type == typeof(Decimal));

            UnmanagedType[] allowed_unmanaged_types =
                (desc.IsStructField ? MarshalType.DecimalField : MarshalType.DecimalParam);

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
            case UnmanagedType.Currency:
            {
                // marshals as CURRENCY COM type
                this.typeName = TypeName.Currency;
                break;
            }

            case UnmanagedType.Struct:
            {
                // marshals as DECIMAL 96-bit type
                this.typeName = TypeName.Decimal;
                break;
            }

            case UnmanagedType.LPStruct:
            {
                // marshals as a pointer to the DECIMAL 96-bit type
                this.isLPStruct = true;
                this.typeName   = TypeName.Decimal;
                this.indirections++;
                break;
            }

            default:
            {
                Debug.Fail(null);
                break;
            }
            }
        }
コード例 #25
0
ファイル: Structs.cs プロジェクト: ARLM-Keller/clr-interop
 public static StructureDefinition Get(NativeTypeDesc desc)
 {
     return(NativeTypeDefinition.Get <StructureDefinition>(
                new TypeDefKey(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags))));
 }
コード例 #26
0
ファイル: Enums.cs プロジェクト: dbremner/clrinterop
        public EnumNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type.IsEnum);

            Type underlying_type = Enum.GetUnderlyingType(desc.Type);

            // verify managed/unmanaged combination (enums are normalized to their underlying type)
            UnmanagedType underlying_unmanaged_type;
            UnmanagedType[] allowed_unmanaged_types = Utility.GetAllowedUnmanagedTypesForEnum(underlying_type);

            if (allowed_unmanaged_types != null)
            {
                // we want the potential validation error to go this type's log
                underlying_unmanaged_type = ValidateUnmanagedType(desc, allowed_unmanaged_types);
            }
            else
            {
                Log.Add(Errors.ERROR_UnexpectedEnumUnderlyingType, underlying_type.FullName);
                underlying_unmanaged_type = UnmanagedType.I4;
            }

            // pass the underlying native type to the definition
            this.typeDefinition = EnumDefinition.Get(desc, underlying_unmanaged_type);
            this.nameModifier = String.Empty;
        }
コード例 #27
0
ファイル: Classes.cs プロジェクト: toiiggww/clrinterop
        public CustomMarshaledNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.MarshalAs != null && desc.MarshalAs.Value == UnmanagedType.CustomMarshaler);

            bool added_error = false;

            if (desc.IsStructField)
            {
                // custom marshalers are not allowed on fields
                Log.Add(Errors.ERROR_CustomMarshalerNotAllowedOnFields);
                added_error = true;
            }

            if (desc.Type.IsValueType)
            {
                // custom marshalers are only allowed on reference types
                Log.Add(Errors.ERROR_CustomMarshalerNotAllowedOnValueTypes);
                added_error = true;
            }

            // try to load the custom marshaler
            Type marshaler_type = null;

            if (desc.MarshalAs.MarshalTypeRef != null)
            {
                marshaler_type = desc.MarshalAs.MarshalTypeRef;
            }
            else
            {
                try
                {
                    marshaler_type = Type.GetType(desc.MarshalAs.MarshalType);
                }
                catch (Exception)
                { }

                if (marshaler_type == null)
                {
                    Log.Add(Errors.WARN_MarshalerTypeNotFound, desc.MarshalAs.MarshalType);
                    added_error = true;
                }
            }

            if (marshaler_type != null)
            {
                // check that the type really is a marshaler
                if (!typeof(ICustomMarshaler).IsAssignableFrom(marshaler_type))
                {
                    Log.Add(Errors.ERROR_MarshalerIsNotICustomMarshaler, marshaler_type.FullName);
                    added_error = true;
                }
                else
                {
                    // check the CreateInstance static method
                    MethodInfo gi_mi;

                    Type type = marshaler_type;
                    do
                    {
                        gi_mi = type.GetMethod(
                            "GetInstance",
                            BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy,
                            null,
                            new Type[] { typeof(string) },
                            null);
                    }while (gi_mi == null && (type = type.BaseType) != null);

                    if (gi_mi == null || gi_mi.ReturnType != typeof(ICustomMarshaler))
                    {
                        Log.Add(Errors.ERROR_MarshalerHasNoGetInstance, marshaler_type.FullName);
                        added_error = true;
                    }
                }
            }

            this.typeName     = TypeName.Void;
            this.indirections = 1;

            if (!added_error)
            {
                Log.Add(Errors.INFO_CustomMarshaledParameter,
                        (marshaler_type != null ? marshaler_type.FullName : desc.MarshalAs.MarshalType));
            }
        }
コード例 #28
0
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.LPArray"/>.
        /// </summary>
        private void InitializeAsNativeArray(NativeTypeDesc desc)
        {
            this.arrayKind = ArrayKind.NativeArray;

            if (desc.IsByRefParam)
            {
                // SizeConst and SizeParamIndex are not allowed for byref
                if (HasSizeConst(desc) || HasSizeParamIndex(desc))
                {
                    Log.Add(Errors.ERROR_ArraySizeNotAllowedForByref);
                }
            }
            else if (!desc.IsCallbackParam)
            {
                // when marshaling from managed to native, size is implicit (warn if given explicitly)
                if (HasSizeConst(desc) || HasSizeParamIndex(desc))
                {
                    Log.Add(Errors.WARN_ArraySizesIgnored);
                }
                else
                {
                    Log.Add(Errors.INFO_ArraySizeDeterminedDynamically);
                }
            }
            else
            {
                // when marshaling from native to managed, size must be given, otherwise it's 1
                if (HasSizeParamIndex(desc))
                {
                    Debug.Assert(desc.ParameterInfo != null);
                    ParameterInfo[] parameters = ((MethodBase)desc.ParameterInfo.Member).GetParameters();

                    int param_index = desc.MarshalAs.SizeParamIndex;
                    if (param_index < 0 || param_index >= parameters.Length)
                    {
                        // index OOR (error)
                        Log.Add(Errors.ERROR_ArraySizeParamIndexOutOfRange, param_index);
                    }
                    else if (!TypeAllowedInSizeParam(parameters[param_index].ParameterType))
                    {
                        // index refers to bad param (error)
                        Log.Add(Errors.ERROR_ArraySizeParamWrongType, parameters[param_index].ParameterType);
                    }
                    else
                    {
                        // determine parameter name
                        string param_name = parameters[param_index].Name;
                        if (String.IsNullOrEmpty(param_name))
                        {
                            param_name = String.Format(Resources.Number, param_index + 1);
                        }

                        if (desc.MarshalAs.SizeConst > 0)
                        {
                            // size = [param_at_the_index] + size_const;
                            Log.Add(Errors.INFO_ArraySizeIsByParameterPlusConstant,
                                    param_name, desc.MarshalAs.SizeConst);
                        }
                        else
                        {
                            // size = [param_at_the_index]
                            Log.Add(Errors.INFO_ArraySizeIsByParameter, param_name);
                        }
                    }
                }
                else if (HasSizeConst(desc))
                {
                    // size = size_const
                    Log.Add(Errors.INFO_ArraySizeIsConstant, desc.MarshalAs.SizeConst);
                }
                else
                {
                    // size = 1 (warn)
                    Log.Add(Errors.WARN_ArraySizeDefaultsToOne);
                }
            }

            UnmanagedType element_unmng_type =
                (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType);

            if (element_unmng_type == (UnmanagedType)80)
            {
                element_unmng_type = (UnmanagedType)0;
            }

            // determine the element type
            this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags);

            ExplainMemoryManagement(desc, Resources._Array);
        }
コード例 #29
0
        public ArrayNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type.IsArray || desc.Type == typeof(System.Array));

            this.platform64bit = desc.IsPlatform64Bit;
            this.indirections  = (desc.IsByRefParam ? 1 : 0);
            this.isInOnly      = (!desc.IsByRefParam && !desc.MarshalsOut); // byval and either [In] or default

            if (!desc.IsStructField)
            {
                this.isByrefParameter = true;
            }

            UnmanagedType[] allowed_unmanaged_types;

            if (desc.Type == typeof(System.Array))
            {
                // System.Array
                if (desc.IsStructField)
                {
                    // interface ptr, SAFEARRAY, or by-val array
                    allowed_unmanaged_types = MarshalType.ArrayClassField;
                }
                else
                {
                    // interface ptr or SAFEARRAY
                    allowed_unmanaged_types = MarshalType.ArrayClass;
                }
            }
            else
            {
                if (desc.IsArrayElement)
                {
                    Log.Add(Errors.ERROR_NoNestedArrayMarshaling);

                    this.arrayKind = ArrayKind.Invalid;
                    return;
                }

                // an array
                if (desc.IsStructField)
                {
                    // default array field marshaling is always COM style, i.e. SAFEARRAY by default
                    allowed_unmanaged_types = MarshalType.ArrayField;
                }
                else
                {
                    // default array parameter marshaling depends on whether we do COM or P/Invoke
                    allowed_unmanaged_types = (desc.IsComInterop ? MarshalType.ArrayC : MarshalType.ArrayP);
                }
            }

            // there are three possible unmanaged types for arrays:
            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
            case UnmanagedType.SafeArray:
            {
                InitializeAsSafeArray(desc);
                break;
            }

            case UnmanagedType.LPArray:
            {
                InitializeAsNativeArray(desc);
                break;
            }

            case UnmanagedType.ByValArray:
            {
                // this unmanaged type only makes sense when we are a field of a type with layout
                Debug.Assert(desc.IsStructField);

                InitializeAsByValArray(desc);
                break;
            }

            default:
            {
                // interfaces are handled by InterfaceNativeType
                Debug.Fail(null);
                break;
            }
            }
        }
コード例 #30
0
ファイル: Enums.cs プロジェクト: dbremner/clrinterop
 public static EnumDefinition Get(NativeTypeDesc desc, UnmanagedType underlyingType)
 {
     if (desc == null) throw new ArgumentNullException(nameof(desc));
     return NativeTypeDefinition.Get<EnumDefinition>(
         new TypeDefKeyWithUnmanagedType(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags), underlyingType));
 }
コード例 #31
0
ファイル: Callbacks.cs プロジェクト: dbremner/clrinterop
        public static NativeTypeDefinition Get(NativeTypeDesc desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            // when a delegate is marshaled as an unmanaged function pointer, its
            // parameters and return type have P/Invoke's default marshaling behavior
            // regardless of whether the function pointer is passed to a static entry
            // point or to a COM member

            return NativeTypeDefinition.Get<FunctionPtrDefinition>(
                new TypeDefKey(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags) & ~MarshalFlags.ComInterop));
        }
コード例 #32
0
ファイル: Classes.cs プロジェクト: kthompson/PInvokeTool
 /// <summary>
 /// Allows the interface name to be specified explicitly.
 /// </summary>
 public InterfaceNativeType(NativeTypeDesc desc, TypeName typeName)
     : base(desc)
 {
     this.typeName = typeName;
     this.isVariant = false;
     this.indirections++;
 }
コード例 #33
0
ファイル: Strings.cs プロジェクト: dbremner/clrinterop
        public StringNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            // the "String *" or "StringBuilder *" type is not allowed
            CheckPointersToReferenceType(desc);

            UnmanagedType ut = DetermineUnmanagedType(desc, out this.immutable);

            // convert the UnmanagedType to TypeName
            switch (ut)
            {
                case UnmanagedType.LPStr:    this.typeName = (immutable ? TypeName.LPCStr : TypeName.LPStr); break;
                case UnmanagedType.LPWStr:   this.typeName = (immutable ? TypeName.LPCWStr : TypeName.LPWStr); break;
                case UnmanagedType.LPTStr:
                {
                    if (desc.AnsiPlatform)
                        this.typeName = (immutable ? TypeName.LPCTStrA : TypeName.LPTStrA);
                    else
                        this.typeName = (immutable ? TypeName.LPCTStrW : TypeName.LPTStrW);

                    Log.Add(Errors.INFO_AutoStringMarshaling);
                    break;
                }

                case UnmanagedType.BStr:     this.typeName = TypeName.BStr;     break;
                case UnmanagedType.AnsiBStr: this.typeName = TypeName.AnsiBStr; break;
                case UnmanagedType.TBStr:
                {
                    this.typeName = (desc.AnsiPlatform ? TypeName.TBStrA : TypeName.TBStrW);

                    Log.Add(Errors.INFO_AutoStringMarshaling);
                    break;
                }

                case UnmanagedType.VBByRefStr:
                {
                    if (!desc.IsByRefParam || desc.PointerIndirections != 0 ||
                        desc.IsCallbackParam || desc.MarshalsIn != desc.MarshalsOut)
                    {
                        Log.Add(Errors.ERROR_VBByRefParamNotByRef);
                    }
                    else
                    {
                        // the marshaler will turn this into (char *) and create a new String object
                        // with the post-call contents of the buffer
                        indirections--;
                    }

                    immutable = false;

                    if (desc.AnsiStrings) goto case UnmanagedType.LPStr;
                    if (desc.UnicodeStrings) goto case UnmanagedType.LPWStr;
                    goto case UnmanagedType.LPTStr;
                }

                case UnmanagedType.ByValTStr:
                {
                    Debug.Assert(desc.IsStructField && this.indirections == 0);

                    // a fixed-length character array will be embedded in the containing structure
                    int length = desc.MarshalAs.SizeConst;
                    if (length <= 0)
                    {
                        Log.Add(Errors.INFO_FixedLengthStringInvalidLength);
                    }

                    this.fixedLength = length;
                    this.fixedLengthAnsi = desc.ShouldMarshalStringsAnsi;

                    if (desc.AnsiStrings) typeName = TypeName.I1;
                    else if (desc.UnicodeStrings) typeName = TypeName.WChar;
                    else typeName = (desc.AnsiPlatform ? TypeName.TCharA : TypeName.TCharW);

                    break;
                }
            }

            // string is a reference type so we are passing ref always
            this.isByrefParameter = !desc.IsStructField;

            if (!desc.IsArrayElement)
            {
                if (immutable && !desc.IsCallbackParam && !desc.IsStructField)
                {
                    if (!desc.IsByRefParam && desc.PointerIndirections == 0 && desc.MarshalsOut)
                    {
                        // we stripped the [Out]
                        Log.Add(Errors.WARN_ByValStringMarkedOut);
                    }
                    else if (!this.MarshalsOut)
                    {
                        Log.Add(Errors.INFO_BewareStringImmutability);
                    }
                }
                else if (desc.Type == typeof(StringBuilder))
                {
                    if (!desc.MarshalsIn && !desc.MarshalsOut)
                    {
                        // StringBuilder goes in/out by default
                        Log.Add(Errors.INFO_DefaultStringBuilderMarshaling);
                    }
                }
            }

            if (ut != UnmanagedType.VBByRefStr &&
                ut != UnmanagedType.ByValTStr) ExplainMemoryManagement(desc, Resources._String);
        }
コード例 #34
0
ファイル: Strings.cs プロジェクト: dbremner/clrinterop
        private UnmanagedType DetermineUnmanagedType(NativeTypeDesc desc, out bool immutable)
        {
            UnmanagedType ut;

            if (desc.Type == typeof(string))
            {
                // only out or in/out by-ref string is mutable
                immutable = (!desc.IsByRefParam || (desc.MarshalsIn && !desc.MarshalsOut));

                UnmanagedType[] allowed_types;
                if (desc.IsStructField)
                {
                    allowed_types = MarshalType.StringField;
                }
                else
                {
                    allowed_types = (desc.IsComInterop ? MarshalType.StringC : MarshalType.StringP);
                }

                ut = ValidateUnmanagedType(desc, allowed_types, UnmanagedType.AsAny);

                if (ut == UnmanagedType.AsAny && !desc.IsStructField && desc.IsComInterop)
                {
                    // BSTR is the default for COM
                    ut = UnmanagedType.BStr;
                }
            }
            else
            {
                Debug.Assert(desc.Type == typeof(StringBuilder));

                immutable = false;

                if (desc.IsStructField)
                {
                    // StringBuilder is only supported by the parameter marshaler
                    Log.Add(Errors.ERROR_StringBuilderFieldsDisallowed);

                    ut = UnmanagedType.LPStr;
                }
                else
                {
                    UnmanagedType[] allowed_types = (desc.IsComInterop ? MarshalType.SBuilderC : MarshalType.SBuilderP);
                    ut = ValidateUnmanagedType(desc, allowed_types, UnmanagedType.AsAny);

                    if (ut == UnmanagedType.AsAny && desc.IsComInterop)
                    {
                        // wide string is the default for COM
                        ut = UnmanagedType.LPWStr;
                    }

                    if (!desc.IsCallbackParam)
                        Log.Add(Errors.INFO_StringBuilderRequiresInit);
                }
            }

            // now determine the default for field marshaling or P/Invoke
            if (ut == UnmanagedType.AsAny)
            {
                Debug.Assert(desc.IsStructField || !desc.IsComInterop);

                if (desc.AnsiStrings) ut = UnmanagedType.LPStr;
                else if (desc.UnicodeStrings) ut = UnmanagedType.LPWStr;
                else ut = UnmanagedType.LPTStr;
            }

            return ut;
        }
コード例 #35
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public VariableArgumentListNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type == typeof(System.ArgIterator));

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            // marshals as va_list
            this.typeName = TypeName.VaList;
        }
コード例 #36
0
ファイル: Classes.cs プロジェクト: toiiggww/clrinterop
        public InterfaceNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            UnmanagedType[] allowed_unmanaged_types;

            if (desc.Type == typeof(System.Object))
            {
                // System.Object
                if (desc.IsArrayElement && !desc.IsStructField)
                {
                    allowed_unmanaged_types = MarshalType.ObjectElement;
                }
                else if (desc.IsStructField)
                {
                    allowed_unmanaged_types = MarshalType.ObjectField;
                }
                else
                {
                    allowed_unmanaged_types = MarshalType.ObjectParam;
                }
            }
            else if (desc.Type == typeof(System.Array))
            {
                // System.Array
                if (desc.MarshalAs == null)
                {
                    if (desc.IsStructField)
                    {
                        Log.Add(Errors.ERROR_UnmanagedTypeRequiredForField, desc.Type.FullName);
                    }
                }

                allowed_unmanaged_types = MarshalType.ArrayClass;
            }
            else
            {
                // an interface
                allowed_unmanaged_types = MarshalType.Interface;
            }

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
            case UnmanagedType.Struct:
            {
                // VARIANT
                this.typeName  = TypeName.Variant;
                this.isVariant = true;
                break;
            }

            case UnmanagedType.Interface:
            case UnmanagedType.IUnknown:
            {
                if (desc.IsArrayElement && !desc.IsStructField)
                {
                    // elements of array parameters are always marshaled as VT_UNKNOWN
                    this.typeName = TypeName.IUnknown;
                }
                else
                {
                    // [ifacename] *
                    SetDefaultComInterface(desc.Type);
                }

                break;
            }

            case UnmanagedType.IDispatch:
            {
                // IDispatch *
                this.typeName = TypeName.IDispatch;
                break;
            }

            case UnmanagedType.AsAny:
            {
                // void *
                this.typeName = TypeName.Void;
                this.indirections++;

                Log.Add(Errors.INFO_AsAnyMarshaling);

                break;
            }

            default:
            {
                Debug.Fail(null);
                break;
            }
            }

            if (isVariant)
            {
                // it is not allowed to marshal return values as VARIANTs
                if (!desc.IsCallbackParam && desc.IsRetValParam)
                {
                    Log.Add(Errors.ERROR_VariantReturnTypeNotSupported);
                }
            }
            else
            {
                // inform about interface pointer AddRefing/Releasing
                if (IsMarshaledNativeToManaged(desc))
                {
                    // RCW will be created
                    Log.Add(Errors.INFO_InterfacePointerToRCWMarshaling);
                }
                if (IsMarshaledManagedToNative(desc))
                {
                    // CCW will be created
                    Log.Add(Errors.INFO_ManagedObjectToCCWMarshaling);
                }
            }
        }
コード例 #37
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public PrimitiveNativeType(NativeTypeDesc desc, UnmanagedType[] allowedUnmanagedTypes)
            : this(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            UnmanagedType unmng_type = ValidateUnmanagedType(desc, allowedUnmanagedTypes);

            if (desc.Type == typeof(bool))
            {
                // Boolean as I1 and I2 should print 'bool' as the plain C++ type
                if (unmng_type == UnmanagedType.I1) typeName = TypeName.I1_Bool;
                if (unmng_type == UnmanagedType.U1) typeName = TypeName.U1_Bool;
            }

            if (typeName.IsEmpty)
            {
                typeName = TypeName.GetTypeNameForUnmanagedType(unmng_type);
                Debug.Assert(!typeName.IsEmpty);
            }

            if (unmng_type == UnmanagedType.SysInt ||
                unmng_type == UnmanagedType.SysUInt)
            {
                // IntPtr and UIntPtr translate into "void *"
                indirections++;
            }
        }
コード例 #38
0
ファイル: Callbacks.cs プロジェクト: dbremner/clrinterop
        public static NativeTypeDefinition Get(NativeTypeDesc desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            // delegates are marshaled as _Delegate COM interface
            // UUID = FB6AB00F-5096-3AF8-A33D-D7885A5FA829

            return NativeTypeDefinition.Get<DelegateInterfaceDefinition>(
                new TypeDefKey(typeof(Delegate), (desc.Flags & MarshalFlags.TypeDefKeyFlags) | MarshalFlags.ComInterop));
        }
コード例 #39
0
 public static EnumDefinition Get(NativeTypeDesc desc, UnmanagedType underlyingType)
 {
     return(NativeTypeDefinition.Get <EnumDefinition>(
                new TypeDefKeyWithUnmanagedType(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags), underlyingType)));
 }
コード例 #40
0
ファイル: Classes.cs プロジェクト: kthompson/PInvokeTool
        public InterfaceNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            UnmanagedType[] allowed_unmanaged_types;

            if (desc.Type == typeof(System.Object))
            {
                // System.Object
                if (desc.IsArrayElement && !desc.IsStructField)
                {
                    allowed_unmanaged_types = MarshalType.ObjectElement;
                }
                else if (desc.IsStructField)
                {
                    allowed_unmanaged_types = MarshalType.ObjectField;
                }
                else
                {
                    allowed_unmanaged_types = MarshalType.ObjectParam;
                }
            }
            else if (desc.Type == typeof(System.Array))
            {
                // System.Array
                if (desc.MarshalAs == null)
                {
                    if (desc.IsStructField)
                    {
                        Log.Add(Errors.ERROR_UnmanagedTypeRequiredForField, desc.Type.FullName);
                    }
                }

                allowed_unmanaged_types = MarshalType.ArrayClass;
            }
            else
            {
                // an interface
                allowed_unmanaged_types = MarshalType.Interface;
            }

            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
                case UnmanagedType.Struct:
                {
                    // VARIANT
                    this.typeName = TypeName.Variant;
                    this.isVariant = true;
                    break;
                }

                case UnmanagedType.Interface:
                case UnmanagedType.IUnknown:
                {
                    if (desc.IsArrayElement && !desc.IsStructField)
                    {
                        // elements of array parameters are always marshaled as VT_UNKNOWN
                        this.typeName = TypeName.IUnknown;
                    }
                    else
                    {
                        // [ifacename] *
                        SetDefaultComInterface(desc.Type);
                    }

                    break;
                }

                case UnmanagedType.IDispatch:
                {
                    // IDispatch *
                    this.typeName = TypeName.IDispatch;
                    break;
                }

                case UnmanagedType.AsAny:
                {
                    // void *
                    this.typeName = TypeName.Void;
                    this.indirections++;

                    Log.Add(Errors.INFO_AsAnyMarshaling);

                    break;
                }

                default:
                {
                    Debug.Fail(null);
                    break;
                }
            }

            if (isVariant)
            {
                // it is not allowed to marshal return values as VARIANTs
                if (!desc.IsCallbackParam && desc.IsRetValParam)
                {
                    Log.Add(Errors.ERROR_VariantReturnTypeNotSupported);
                }
            }
            else
            {
                // inform about interface pointer AddRefing/Releasing
                if (IsMarshaledNativeToManaged(desc))
                {
                    // RCW will be created
                    Log.Add(Errors.INFO_InterfacePointerToRCWMarshaling);
                }
                if (IsMarshaledManagedToNative(desc))
                {
                    // CCW will be created
                    Log.Add(Errors.INFO_ManagedObjectToCCWMarshaling);
                }
            }
        }
コード例 #41
0
        public StringNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            // the "String *" or "StringBuilder *" type is not allowed
            CheckPointersToReferenceType(desc);

            UnmanagedType ut = DetermineUnmanagedType(desc, out this.immutable);

            // convert the UnmanagedType to TypeName
            switch (ut)
            {
            case UnmanagedType.LPStr:    this.typeName = (immutable ? TypeName.LPCStr : TypeName.LPStr); break;

            case UnmanagedType.LPWStr:   this.typeName = (immutable ? TypeName.LPCWStr : TypeName.LPWStr); break;

            case UnmanagedType.LPTStr:
            {
                if (desc.AnsiPlatform)
                {
                    this.typeName = (immutable ? TypeName.LPCTStrA : TypeName.LPTStrA);
                }
                else
                {
                    this.typeName = (immutable ? TypeName.LPCTStrW : TypeName.LPTStrW);
                }

                Log.Add(Errors.INFO_AutoStringMarshaling);
                break;
            }

            case UnmanagedType.BStr:     this.typeName = TypeName.BStr;     break;

            case UnmanagedType.AnsiBStr: this.typeName = TypeName.AnsiBStr; break;

            case UnmanagedType.TBStr:
            {
                this.typeName = (desc.AnsiPlatform ? TypeName.TBStrA : TypeName.TBStrW);

                Log.Add(Errors.INFO_AutoStringMarshaling);
                break;
            }

            case UnmanagedType.VBByRefStr:
            {
                if (!desc.IsByRefParam || desc.PointerIndirections != 0 ||
                    desc.IsCallbackParam || desc.MarshalsIn != desc.MarshalsOut)
                {
                    Log.Add(Errors.ERROR_VBByRefParamNotByRef);
                }
                else
                {
                    // the marshaler will turn this into (char *) and create a new String object
                    // with the post-call contents of the buffer
                    indirections--;
                }

                immutable = false;

                if (desc.AnsiStrings)
                {
                    goto case UnmanagedType.LPStr;
                }
                if (desc.UnicodeStrings)
                {
                    goto case UnmanagedType.LPWStr;
                }
                goto case UnmanagedType.LPTStr;
            }

            case UnmanagedType.ByValTStr:
            {
                Debug.Assert(desc.IsStructField && this.indirections == 0);

                // a fixed-length character array will be embedded in the containing structure
                int length = desc.MarshalAs.SizeConst;
                if (length <= 0)
                {
                    Log.Add(Errors.INFO_FixedLengthStringInvalidLength);
                }

                this.fixedLength     = length;
                this.fixedLengthAnsi = desc.ShouldMarshalStringsAnsi;

                if (desc.AnsiStrings)
                {
                    typeName = TypeName.I1;
                }
                else if (desc.UnicodeStrings)
                {
                    typeName = TypeName.WChar;
                }
                else
                {
                    typeName = (desc.AnsiPlatform ? TypeName.TCharA : TypeName.TCharW);
                }

                break;
            }
            }

            // string is a reference type so we are passing ref always
            this.isByrefParameter = !desc.IsStructField;

            if (!desc.IsArrayElement)
            {
                if (immutable && !desc.IsCallbackParam && !desc.IsStructField)
                {
                    if (!desc.IsByRefParam && desc.PointerIndirections == 0 && desc.MarshalsOut)
                    {
                        // we stripped the [Out]
                        Log.Add(Errors.WARN_ByValStringMarkedOut);
                    }
                    else if (!this.MarshalsOut)
                    {
                        Log.Add(Errors.INFO_BewareStringImmutability);
                    }
                }
                else if (desc.Type == typeof(StringBuilder))
                {
                    if (!desc.MarshalsIn && !desc.MarshalsOut)
                    {
                        // StringBuilder goes in/out by default
                        Log.Add(Errors.INFO_DefaultStringBuilderMarshaling);
                    }
                }
            }

            if (ut != UnmanagedType.VBByRefStr &&
                ut != UnmanagedType.ByValTStr)
            {
                ExplainMemoryManagement(desc, Resources._String);
            }
        }
コード例 #42
0
ファイル: Classes.cs プロジェクト: kthompson/PInvokeTool
        public CustomMarshaledNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.MarshalAs != null && desc.MarshalAs.Value == UnmanagedType.CustomMarshaler);

            bool added_error = false;

            if (desc.IsStructField)
            {
                // custom marshalers are not allowed on fields
                Log.Add(Errors.ERROR_CustomMarshalerNotAllowedOnFields);
                added_error = true;
            }

            if (desc.Type.IsValueType)
            {
                // custom marshalers are only allowed on reference types
                Log.Add(Errors.ERROR_CustomMarshalerNotAllowedOnValueTypes);
                added_error = true;
            }

            // try to load the custom marshaler
            Type marshaler_type = null;
            if (desc.MarshalAs.MarshalTypeRef != null)
            {
                marshaler_type = desc.MarshalAs.MarshalTypeRef;
            }
            else
            {
                try
                {
                    marshaler_type = Type.GetType(desc.MarshalAs.MarshalType);
                }
                catch (Exception)
                { }

                if (marshaler_type == null)
                {
                    Log.Add(Errors.WARN_MarshalerTypeNotFound, desc.MarshalAs.MarshalType);
                    added_error = true;
                }
            }

            if (marshaler_type != null)
            {
                // check that the type really is a marshaler
                if (!typeof(ICustomMarshaler).IsAssignableFrom(marshaler_type))
                {
                    Log.Add(Errors.ERROR_MarshalerIsNotICustomMarshaler, marshaler_type.FullName);
                    added_error = true;
                }
                else
                {
                    // check the CreateInstance static method
                    MethodInfo gi_mi;

                    Type type = marshaler_type;
                    do
                    {
                        gi_mi = type.GetMethod(
                            "GetInstance",
                            BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy,
                            null,
                            new Type[] { typeof(string) },
                            null);
                    }
                    while (gi_mi == null && (type = type.BaseType) != null);

                    if (gi_mi == null || gi_mi.ReturnType != typeof(ICustomMarshaler))
                    {
                        Log.Add(Errors.ERROR_MarshalerHasNoGetInstance, marshaler_type.FullName);
                        added_error = true;
                    }
                }
            }

            this.typeName = TypeName.Void;
            this.indirections = 1;

            if (!added_error)
            {
                Log.Add(Errors.INFO_CustomMarshaledParameter,
                    (marshaler_type != null ? marshaler_type.FullName : desc.MarshalAs.MarshalType));
            }
        }
コード例 #43
0
        private UnmanagedType DetermineUnmanagedType(NativeTypeDesc desc, out bool immutable)
        {
            UnmanagedType ut;

            if (desc.Type == typeof(string))
            {
                // only out or in/out by-ref string is mutable
                immutable = (!desc.IsByRefParam || (desc.MarshalsIn && !desc.MarshalsOut));

                UnmanagedType[] allowed_types;
                if (desc.IsStructField)
                {
                    allowed_types = MarshalType.StringField;
                }
                else
                {
                    allowed_types = (desc.IsComInterop ? MarshalType.StringC : MarshalType.StringP);
                }

                ut = ValidateUnmanagedType(desc, allowed_types, UnmanagedType.AsAny);

                if (ut == UnmanagedType.AsAny && !desc.IsStructField && desc.IsComInterop)
                {
                    // BSTR is the default for COM
                    ut = UnmanagedType.BStr;
                }
            }
            else
            {
                Debug.Assert(desc.Type == typeof(StringBuilder));

                immutable = false;

                if (desc.IsStructField)
                {
                    // StringBuilder is only supported by the parameter marshaler
                    Log.Add(Errors.ERROR_StringBuilderFieldsDisallowed);

                    ut = UnmanagedType.LPStr;
                }
                else
                {
                    UnmanagedType[] allowed_types = (desc.IsComInterop ? MarshalType.SBuilderC : MarshalType.SBuilderP);
                    ut = ValidateUnmanagedType(desc, allowed_types, UnmanagedType.AsAny);

                    if (ut == UnmanagedType.AsAny && desc.IsComInterop)
                    {
                        // wide string is the default for COM
                        ut = UnmanagedType.LPWStr;
                    }

                    if (!desc.IsCallbackParam)
                    {
                        Log.Add(Errors.INFO_StringBuilderRequiresInit);
                    }
                }
            }

            // now determine the default for field marshaling or P/Invoke
            if (ut == UnmanagedType.AsAny)
            {
                Debug.Assert(desc.IsStructField || !desc.IsComInterop);

                if (desc.AnsiStrings)
                {
                    ut = UnmanagedType.LPStr;
                }
                else if (desc.UnicodeStrings)
                {
                    ut = UnmanagedType.LPWStr;
                }
                else
                {
                    ut = UnmanagedType.LPTStr;
                }
            }

            return(ut);
        }
コード例 #44
0
ファイル: Arrays.cs プロジェクト: kthompson/PInvokeTool
        public ArrayNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            Debug.Assert(desc.Type.IsArray || desc.Type == typeof(System.Array));

            this.platform64bit = desc.IsPlatform64Bit;
            this.indirections = (desc.IsByRefParam ? 1 : 0);
            this.isInOnly = (!desc.IsByRefParam && !desc.MarshalsOut); // byval and either [In] or default

            if (!desc.IsStructField)
                this.isByrefParameter = true;

            UnmanagedType[] allowed_unmanaged_types;

            if (desc.Type == typeof(System.Array))
            {
                // System.Array
                if (desc.IsStructField)
                {
                    // interface ptr, SAFEARRAY, or by-val array
                    allowed_unmanaged_types = MarshalType.ArrayClassField;
                }
                else
                {
                    // interface ptr or SAFEARRAY
                    allowed_unmanaged_types = MarshalType.ArrayClass;
                }
            }
            else
            {
                if (desc.IsArrayElement)
                {
                    Log.Add(Errors.ERROR_NoNestedArrayMarshaling);

                    this.arrayKind = ArrayKind.Invalid;
                    return;
                }

                // an array
                if (desc.IsStructField)
                {
                    // default array field marshaling is always COM style, i.e. SAFEARRAY by default
                    allowed_unmanaged_types = MarshalType.ArrayField;
                }
                else
                {
                    // default array parameter marshaling depends on whether we do COM or P/Invoke
                    allowed_unmanaged_types = (desc.IsComInterop ? MarshalType.ArrayC : MarshalType.ArrayP);
                }
            }

            // there are three possible unmanaged types for arrays:
            switch (ValidateUnmanagedType(desc, allowed_unmanaged_types))
            {
                case UnmanagedType.SafeArray:
                {
                    InitializeAsSafeArray(desc);
                    break;
                }

                case UnmanagedType.LPArray:
                {
                    InitializeAsNativeArray(desc);
                    break;
                }

                case UnmanagedType.ByValArray:
                {
                    // this unmanaged type only makes sense when we are a field of a type with layout
                    Debug.Assert(desc.IsStructField);

                    InitializeAsByValArray(desc);
                    break;
                }

                default:
                {
                    // interfaces are handled by InterfaceNativeType
                    Debug.Fail(null);
                    break;
                }
            }
        }
コード例 #45
0
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.SafeArray"/>.
        /// </summary>
        private void InitializeAsSafeArray(NativeTypeDesc desc)
        {
            this.arrayKind = ArrayKind.SafeArray;

            Type array_mng_type = desc.Type;

            VarEnum sub_type = VarEnum.VT_EMPTY;

            if (desc.MarshalAs != null && desc.MarshalAs.SafeArraySubType != VarEnum.VT_EMPTY)
            {
                sub_type = desc.MarshalAs.SafeArraySubType;
            }
            else
            {
                // the unmanaged type may also be specified statically using one of the wrapper classes
                if (array_mng_type == typeof(UnknownWrapper[]))
                {
                    array_mng_type = typeof(object[]);
                    sub_type       = VarEnum.VT_UNKNOWN;
                }
                else if (array_mng_type == typeof(DispatchWrapper[]))
                {
                    array_mng_type = typeof(object[]);
                    sub_type       = VarEnum.VT_DISPATCH;
                }
                else if (array_mng_type == typeof(ErrorWrapper[]))
                {
                    array_mng_type = typeof(int[]);
                    sub_type       = VarEnum.VT_ERROR;
                }
                else if (array_mng_type == typeof(CurrencyWrapper[]))
                {
                    array_mng_type = typeof(Decimal[]);
                    sub_type       = VarEnum.VT_CY;
                }
                else if (array_mng_type == typeof(BStrWrapper[]))
                {
                    array_mng_type = typeof(string[]);
                    sub_type       = VarEnum.VT_BSTR;
                }
            }

            // convert the SafeArraySubType to UnmanagedType
            UnmanagedType element_unmng_type = Utility.VarEnumToUnmanagedType(sub_type);

            // determine the element type
            // (this will have no effect on the C++ signature but we will check it and add it to log)
            this.elementType = NativeType.FromClrArrayElement(
                array_mng_type,
                element_unmng_type,
                (desc.Flags & ~MarshalFlags.ByRefParam) | MarshalFlags.ComInterop);

            if (sub_type == VarEnum.VT_EMPTY)
            {
                sub_type = Utility.TypeToVarEnum(array_mng_type.GetElementType());
            }

            if (!elementType.IsInvalid)
            {
                if (array_mng_type != typeof(System.Array) || sub_type != VarEnum.VT_EMPTY)
                {
                    // log the element native type
                    Log.Add(Errors.INFO_SafeArrayWillMarshalAs, sub_type.ToString());
                }
            }

            // also include the *Wrapper hint if applicable
            if (desc.Type == typeof(object[]) && (sub_type == VarEnum.VT_EMPTY || sub_type == VarEnum.VT_VARIANT))
            {
                Log.Add(Errors.INFO_SafeArrayOfVariantsWrapperUse);
            }

            ExplainMemoryManagement(desc, Resources._SafeArray);
        }
コード例 #46
0
ファイル: Arrays.cs プロジェクト: kthompson/PInvokeTool
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.LPArray"/>.
        /// </summary>
        private void InitializeAsNativeArray(NativeTypeDesc desc)
        {
            this.arrayKind = ArrayKind.NativeArray;

            if (desc.IsByRefParam)
            {
                // SizeConst and SizeParamIndex are not allowed for byref
                if (HasSizeConst(desc) || HasSizeParamIndex(desc))
                {
                    Log.Add(Errors.ERROR_ArraySizeNotAllowedForByref);
                }
            }
            else if (!desc.IsCallbackParam)
            {
                // when marshaling from managed to native, size is implicit (warn if given explicitly)
                if (HasSizeConst(desc) || HasSizeParamIndex(desc))
                {
                    Log.Add(Errors.WARN_ArraySizesIgnored);
                }
                else
                {
                    Log.Add(Errors.INFO_ArraySizeDeterminedDynamically);
                }
            }
            else
            {
                // when marshaling from native to managed, size must be given, otherwise it's 1
                if (HasSizeParamIndex(desc))
                {
                    Debug.Assert(desc.ParameterInfo != null);
                    ParameterInfo[] parameters = ((MethodBase)desc.ParameterInfo.Member).GetParameters();

                    int param_index = desc.MarshalAs.SizeParamIndex;
                    if (param_index < 0 || param_index >= parameters.Length)
                    {
                        // index OOR (error)
                        Log.Add(Errors.ERROR_ArraySizeParamIndexOutOfRange, param_index);
                    }
                    else if (!TypeAllowedInSizeParam(parameters[param_index].ParameterType))
                    {
                        // index refers to bad param (error)
                        Log.Add(Errors.ERROR_ArraySizeParamWrongType,parameters[param_index].ParameterType);
                    }
                    else
                    {
                        // determine parameter name
                        string param_name = parameters[param_index].Name;
                        if (String.IsNullOrEmpty(param_name))
                        {
                            param_name = String.Format(Resources.Number, param_index + 1);
                        }

                        if (desc.MarshalAs.SizeConst > 0)
                        {
                            // size = [param_at_the_index] + size_const;
                            Log.Add(Errors.INFO_ArraySizeIsByParameterPlusConstant,
                                param_name, desc.MarshalAs.SizeConst);
                        }
                        else
                        {
                            // size = [param_at_the_index]
                            Log.Add(Errors.INFO_ArraySizeIsByParameter, param_name);
                        }
                    }
                }
                else if (HasSizeConst(desc))
                {
                    // size = size_const
                    Log.Add(Errors.INFO_ArraySizeIsConstant, desc.MarshalAs.SizeConst);
                }
                else
                {
                    // size = 1 (warn)
                    Log.Add(Errors.WARN_ArraySizeDefaultsToOne);
                }
            }

            UnmanagedType element_unmng_type =
                (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType);
            if (element_unmng_type == (UnmanagedType)80) element_unmng_type = (UnmanagedType)0;

            // determine the element type
            this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags);

            ExplainMemoryManagement(desc, Resources._Array);
        }
コード例 #47
0
ファイル: Classes.cs プロジェクト: kthompson/PInvokeTool
 private static bool IsMarshaledNativeToManaged(NativeTypeDesc desc)
 {
     if (desc.IsCallbackParam)
     {
         return (desc.MarshalsIn || (!desc.MarshalsOut && !desc.IsRetValParam));
     }
     else
     {
         return (desc.IsRetValParam || desc.MarshalsOut);
     }
 }
コード例 #48
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        protected PrimitiveNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            this.platform64bit = desc.IsPlatform64Bit;

            // count the total level of indirections
            this.indirections = desc.PointerIndirections;
            if (desc.IsByRefParam) this.indirections++;

            VerifyMarshalDirection(desc);
        }
コード例 #49
0
ファイル: Arrays.cs プロジェクト: kthompson/PInvokeTool
 private static bool HasSizeParamIndex(NativeTypeDesc desc)
 {
     // Warning: there is currently no way how we can distinguish between the case where SizeParamIndex
     // is not specified and the case where SizeParamIndex is specified and set to 0. This method should
     // be updated when the MarshalAsAttribute is improved to provide this information.
     if (desc.MarshalAs == null) return false;
     return (desc.MarshalAs.SizeParamIndex != 0);
 }
コード例 #50
0
ファイル: Structs.cs プロジェクト: ARLM-Keller/clr-interop
        private void ExplainPinningOrCopying(NativeTypeDesc desc, bool isBlittable)
        {
            if (!desc.IsCallbackParam)
            {
                if (isBlittable)
                {
                    // blittable parameter will be pinned
                    Log.Add(Errors.INFO_LayoutBlittableParameter, desc.Type.FullName);

                    WarnBlittableInOutMismatch(desc);
                }
                else
                {
                    // non-blittable parameter will be copied
                    Log.Add(Errors.INFO_LayoutNonBlittableParameter, desc.Type.FullName);

                    if ((desc.MarshalsIn && !desc.MarshalsOut) ||
                        (byDefaultInOnly && !desc.MarshalsIn && !desc.MarshalsOut))
                    {
                        // managed -> native
                        Log.Add(Errors.INFO_LayoutDirectionManagedToNative, desc.Type.FullName);
                        isConstPointer = true;
                    }
                    else if (!desc.MarshalsIn && desc.MarshalsOut)
                    {
                        // managed <- native
                        Log.Add(Errors.INFO_LayoutDirectionNativeToManaged, desc.Type.FullName);
                    }
                    else
                    {
                        // managed <-> native
                        Log.Add(Errors.INFO_LayoutDirectionBoth, desc.Type.FullName);
                    }
                }
            }
            else
            {
                // this is a callback so everything is reversed
                if (isBlittable)
                {
                    // blittable parameter means managed directly accesses unmanaged
                    Log.Add(Errors.INFO_LayoutBlittableCallbackParameter, desc.Type.FullName);

                    WarnBlittableInOutMismatch(desc);
                }
                else
                {
                    // non-blittable parameter will be copied
                    Log.Add(Errors.INFO_LayoutNonBlittableCallbackParameter, desc.Type.FullName);

                    if ((desc.MarshalsIn && !desc.MarshalsOut) ||
                        (byDefaultInOnly && !desc.MarshalsIn && !desc.MarshalsOut))
                    {
                        // managed <- native
                        Log.Add(Errors.INFO_LayoutDirectionNativeToManaged, desc.Type.FullName);
                        isConstPointer = true;
                    }
                    else if (!desc.MarshalsIn && desc.MarshalsOut)
                    {
                        // managed -> native
                        Log.Add(Errors.INFO_LayoutDirectionManagedToNative, desc.Type.FullName);
                    }
                    else
                    {
                        // managed <-> native
                        Log.Add(Errors.INFO_LayoutDirectionBoth, desc.Type.FullName);
                    }
                }
            }
        }
コード例 #51
0
ファイル: Arrays.cs プロジェクト: kthompson/PInvokeTool
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.ByValArray"/>.
        /// </summary>
        private void InitializeAsByValArray(NativeTypeDesc desc)
        {
            Debug.Assert(this.indirections == 0);

            this.arrayKind = ArrayKind.ByValArray;

            // const size must be specified and >0
            if (desc.MarshalAs == null || desc.MarshalAs.SizeConst <= 0)
            {
                Log.Add(Errors.ERROR_ByValArrayInvalidLength);
                this.length = 1;
            }
            else
            {
                // no need to output any INFO as this number will be between brackets in the code
                this.length = desc.MarshalAs.SizeConst;
            }

            UnmanagedType element_unmng_type =
                (desc.MarshalAs == null ? (UnmanagedType)0 : desc.MarshalAs.ArraySubType);
            if (element_unmng_type == (UnmanagedType)80) element_unmng_type = (UnmanagedType)0;

            // determine the element type
            this.elementType = NativeType.FromClrArrayElement(desc.Type, element_unmng_type, desc.Flags);
        }
コード例 #52
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public HandleNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(
                desc.Type == typeof(System.Runtime.InteropServices.HandleRef) ||
                typeof(System.Runtime.InteropServices.SafeHandle).IsAssignableFrom(desc.Type) ||
                typeof(System.Runtime.InteropServices.CriticalHandle).IsAssignableFrom(desc.Type));

            if (desc.IsArrayElement && desc.Type != typeof(System.Runtime.InteropServices.HandleRef))
            {
                Log.Add(Errors.ERROR_HandlesNotPermittedAsArrayElements);
            }

            // non-default marshaling is not supported
            ValidateUnmanagedType(desc, MarshalType.Empty);

            // marshals as HANDLE
            this.typeName = TypeName.Handle;
        }
コード例 #53
0
ファイル: Arrays.cs プロジェクト: kthompson/PInvokeTool
        /// <summary>
        /// Initializes the array as a <see cref="UnmanagedType.SafeArray"/>.
        /// </summary>
        private void InitializeAsSafeArray(NativeTypeDesc desc)
        {
            this.arrayKind = ArrayKind.SafeArray;

            Type array_mng_type = desc.Type;

            VarEnum sub_type = VarEnum.VT_EMPTY;
            if (desc.MarshalAs != null && desc.MarshalAs.SafeArraySubType != VarEnum.VT_EMPTY)
            {
                sub_type = desc.MarshalAs.SafeArraySubType;
            }
            else
            {
                // the unmanaged type may also be specified statically using one of the wrapper classes
                if (array_mng_type == typeof(UnknownWrapper[]))
                {
                    array_mng_type = typeof(object[]);
                    sub_type = VarEnum.VT_UNKNOWN;
                }
                else if (array_mng_type == typeof(DispatchWrapper[]))
                {
                    array_mng_type = typeof(object[]);
                    sub_type = VarEnum.VT_DISPATCH;
                }
                else if (array_mng_type == typeof(ErrorWrapper[]))
                {
                    array_mng_type = typeof(int[]);
                    sub_type = VarEnum.VT_ERROR;
                }
                else if (array_mng_type == typeof(CurrencyWrapper[]))
                {
                    array_mng_type = typeof(Decimal[]);
                    sub_type = VarEnum.VT_CY;
                }
                else if (array_mng_type == typeof(BStrWrapper[]))
                {
                    array_mng_type = typeof(string[]);
                    sub_type = VarEnum.VT_BSTR;
                }
            }

            // convert the SafeArraySubType to UnmanagedType
            UnmanagedType element_unmng_type = Utility.VarEnumToUnmanagedType(sub_type);

            // determine the element type
            // (this will have no effect on the C++ signature but we will check it and add it to log)
            this.elementType = NativeType.FromClrArrayElement(
                array_mng_type,
                element_unmng_type,
                (desc.Flags & ~MarshalFlags.ByRefParam) | MarshalFlags.ComInterop);

            if (sub_type == VarEnum.VT_EMPTY)
            {
                sub_type = Utility.TypeToVarEnum(array_mng_type.GetElementType());
            }

            if (!elementType.IsInvalid)
            {
                if (array_mng_type != typeof(System.Array) || sub_type != VarEnum.VT_EMPTY)
                {
                    // log the element native type
                    Log.Add(Errors.INFO_SafeArrayWillMarshalAs, sub_type.ToString());
                }
            }

            // also include the *Wrapper hint if applicable
            if (desc.Type == typeof(object[]) && (sub_type == VarEnum.VT_EMPTY || sub_type == VarEnum.VT_VARIANT))
            {
                Log.Add(Errors.INFO_SafeArrayOfVariantsWrapperUse);
            }

            ExplainMemoryManagement(desc, Resources._SafeArray);
        }
コード例 #54
0
ファイル: Primitives.cs プロジェクト: dbremner/clrinterop
        public GuidNativeType(NativeTypeDesc desc)
            : base(desc)
        {
            if (desc == null) throw new ArgumentNullException(nameof(desc));
            Debug.Assert(desc.Type == typeof(System.Guid));

            if (ValidateUnmanagedType(desc, MarshalType.Guid) == UnmanagedType.LPStruct)
            {
                this.isLPStruct = true;
                this.indirections++;
            }

            // marshals as either GUID or PGUID
            this.typeName = TypeName.Guid;
        }