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++; } }
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; }
/// <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++; }
/// <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); }
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; } }
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))); }
public DateNativeType(NativeTypeDesc desc) : base(desc) { Debug.Assert(desc.Type == typeof(DateTime)); ValidateUnmanagedType(desc, MarshalType.Struct); this.typeName = TypeName.Date; }
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; }
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))); }
private static bool IsMarshaledManagedToNative(NativeTypeDesc desc) { if (desc.IsCallbackParam) { return(desc.IsRetValParam || desc.MarshalsOut); } else { return(desc.MarshalsIn || (!desc.MarshalsOut && !desc.IsRetValParam)); } }
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); }
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; }
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); } }
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); }
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; } } }
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; } } }
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; }
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); }
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; }
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; } }
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; }
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; }
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; } } }
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; } } }
public static StructureDefinition Get(NativeTypeDesc desc) { return(NativeTypeDefinition.Get <StructureDefinition>( new TypeDefKey(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags)))); }
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; }
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)); } }
/// <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); }
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; } } }
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)); }
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)); }
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); }
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; }
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; }
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); } } }
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++; } }
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)); }
public static EnumDefinition Get(NativeTypeDesc desc, UnmanagedType underlyingType) { return(NativeTypeDefinition.Get <EnumDefinition>( new TypeDefKeyWithUnmanagedType(desc.Type, (desc.Flags & MarshalFlags.TypeDefKeyFlags), underlyingType))); }
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); } }
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)); } }
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); }
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; } } }
/// <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); }
/// <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); }
private static bool IsMarshaledNativeToManaged(NativeTypeDesc desc) { if (desc.IsCallbackParam) { return (desc.MarshalsIn || (!desc.MarshalsOut && !desc.IsRetValParam)); } else { return (desc.IsRetValParam || desc.MarshalsOut); } }
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); }
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); }
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); } } } }
/// <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); }
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; }
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; }