internal void SetMarshalAsSafeArray(VarEnum?elementType, ITypeSymbol elementTypeSymbol) { Debug.Assert(elementType == null || elementType >= 0 && (int)elementType <= MaxMarshalInteger); this.marshalType = UnmanagedType.SafeArray; this.marshalArrayElementType = (int)(elementType ?? InvalidVariantType); this.marshalTypeNameOrSymbol = elementTypeSymbol; }
internal static CustomAttributeData GetMarshalAsAttribute(Module module, int token) { // TODO use binary search? for (int i = 0; i < module.FieldMarshal.records.Length; i++) { if (module.FieldMarshal.records[i].Parent == token) { ByteReader blob = module.GetBlob(module.FieldMarshal.records[i].NativeType); UnmanagedType unmanagedType = (UnmanagedType)blob.ReadCompressedInt(); UnmanagedType?arraySubType = null; short? sizeParamIndex = null; int? sizeConst = null; VarEnum? safeArraySubType = null; Type safeArrayUserDefinedSubType = null; int? iidParameterIndex = null; string marshalType = null; string marshalCookie = null; Type marshalTypeRef = null; if (unmanagedType == UnmanagedType.LPArray) { arraySubType = (UnmanagedType)blob.ReadCompressedInt(); if (arraySubType == NATIVE_TYPE_MAX) { arraySubType = null; } if (blob.Length != 0) { sizeParamIndex = (short)blob.ReadCompressedInt(); if (blob.Length != 0) { sizeConst = blob.ReadCompressedInt(); if (blob.Length != 0 && blob.ReadCompressedInt() == 0) { sizeParamIndex = null; } } } } else if (unmanagedType == UnmanagedType.SafeArray) { if (blob.Length != 0) { safeArraySubType = (VarEnum)blob.ReadCompressedInt(); if (blob.Length != 0) { safeArrayUserDefinedSubType = ReadType(module, blob); } } } else if (unmanagedType == UnmanagedType.ByValArray) { sizeConst = blob.ReadCompressedInt(); if (blob.Length != 0) { arraySubType = (UnmanagedType)blob.ReadCompressedInt(); } } else if (unmanagedType == UnmanagedType.ByValTStr) { sizeConst = blob.ReadCompressedInt(); } else if (unmanagedType == UnmanagedType.Interface || unmanagedType == UnmanagedType.IDispatch || unmanagedType == UnmanagedType.IUnknown) { if (blob.Length != 0) { iidParameterIndex = blob.ReadCompressedInt(); } } else if (unmanagedType == UnmanagedType.CustomMarshaler) { blob.ReadCompressedInt(); blob.ReadCompressedInt(); marshalType = ReadString(blob); marshalCookie = ReadString(blob); TypeNameParser parser = TypeNameParser.Parse(marshalType, false); if (!parser.Error) { marshalTypeRef = parser.GetType(module.universe, module.Assembly, false, marshalType, false); } } Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute; Type typeofUnmanagedType = module.universe.System_Runtime_InteropServices_UnmanagedType; Type typeofVarEnum = module.universe.System_Runtime_InteropServices_VarEnum; Type typeofType = module.universe.System_Type; List <CustomAttributeNamedArgument> named = new List <CustomAttributeNamedArgument>(); if (arraySubType != null) { AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, arraySubType.Value); } if (sizeParamIndex != null) { AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.universe.System_Int16, sizeParamIndex.Value); } if (sizeConst != null) { AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.universe.System_Int32, sizeConst.Value); } if (safeArraySubType != null) { AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, safeArraySubType.Value); } if (safeArrayUserDefinedSubType != null) { AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, safeArrayUserDefinedSubType); } if (iidParameterIndex != null) { AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.universe.System_Int32, iidParameterIndex.Value); } if (marshalType != null) { AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.universe.System_String, marshalType); } if (marshalTypeRef != null) { AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.universe.System_Type, marshalTypeRef); } if (marshalCookie != null) { AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.universe.System_String, marshalCookie); } ConstructorInfo constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType); return(new CustomAttributeData(module, constructor, new object[] { unmanagedType }, named)); } } throw new BadImageFormatException(); }
private static int WriteMarshallingDescriptor(ModuleBuilder module, CustomAttributeBuilder attribute) { UnmanagedType unmanagedType; object val = attribute.GetConstructorArgument(0); if (val is short) { unmanagedType = (UnmanagedType)(short)val; } else if (val is int) { unmanagedType = (UnmanagedType)(int)val; } else { unmanagedType = (UnmanagedType)val; } ByteBuffer bb = new ByteBuffer(5); bb.WriteCompressedInt((int)unmanagedType); if (unmanagedType == UnmanagedType.LPArray) { UnmanagedType arraySubType = attribute.GetFieldValue <UnmanagedType>("ArraySubType") ?? NATIVE_TYPE_MAX; bb.WriteCompressedInt((int)arraySubType); int?sizeParamIndex = attribute.GetFieldValue <short>("SizeParamIndex"); int?sizeConst = attribute.GetFieldValue <int>("SizeConst"); if (sizeParamIndex != null) { bb.WriteCompressedInt(sizeParamIndex.Value); if (sizeConst != null) { bb.WriteCompressedInt(sizeConst.Value); bb.WriteCompressedInt(1); // flag that says that SizeParamIndex was specified } } else if (sizeConst != null) { bb.WriteCompressedInt(0); // SizeParamIndex bb.WriteCompressedInt(sizeConst.Value); bb.WriteCompressedInt(0); // flag that says that SizeParamIndex was not specified } } else if (unmanagedType == UnmanagedType.SafeArray) { VarEnum?safeArraySubType = attribute.GetFieldValue <VarEnum>("SafeArraySubType"); if (safeArraySubType != null) { bb.WriteCompressedInt((int)safeArraySubType); Type safeArrayUserDefinedSubType = (Type)attribute.GetFieldValue("SafeArrayUserDefinedSubType"); if (safeArrayUserDefinedSubType != null) { WriteType(module, bb, safeArrayUserDefinedSubType); } } } else if (unmanagedType == UnmanagedType.ByValArray) { bb.WriteCompressedInt(attribute.GetFieldValue <int>("SizeConst") ?? 1); UnmanagedType?arraySubType = attribute.GetFieldValue <UnmanagedType>("ArraySubType"); if (arraySubType != null) { bb.WriteCompressedInt((int)arraySubType); } } else if (unmanagedType == UnmanagedType.ByValTStr) { bb.WriteCompressedInt(attribute.GetFieldValue <int>("SizeConst").Value); } else if (unmanagedType == UnmanagedType.Interface || unmanagedType == UnmanagedType.IDispatch || unmanagedType == UnmanagedType.IUnknown) { int?iidParameterIndex = attribute.GetFieldValue <int>("IidParameterIndex"); if (iidParameterIndex != null) { bb.WriteCompressedInt(iidParameterIndex.Value); } } else if (unmanagedType == UnmanagedType.CustomMarshaler) { bb.WriteCompressedInt(0); bb.WriteCompressedInt(0); string marshalType = (string)attribute.GetFieldValue("MarshalType"); if (marshalType != null) { WriteString(bb, marshalType); } else { WriteType(module, bb, (Type)attribute.GetFieldValue("MarshalTypeRef")); } WriteString(bb, (string)attribute.GetFieldValue("MarshalCookie") ?? ""); } return(module.Blobs.Add(bb)); }
private static void DecodeMarshalAsSafeArray(ref DecodeWellKnownAttributeArguments <TAttributeSyntax, TAttributeData, TAttributeLocation> arguments, CommonMessageProvider messageProvider) { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); VarEnum? elementTypeVariant = null; ITypeSymbol elementTypeSymbol = null; int symbolIndex = -1; bool hasErrors = false; int position = 1; foreach (var namedArg in arguments.Attribute.NamedArguments) { switch (namedArg.Key) { case "SafeArraySubType": elementTypeVariant = namedArg.Value.DecodeValue <VarEnum>(SpecialType.System_Enum); if (elementTypeVariant < 0 || (int)elementTypeVariant > MarshalPseudoCustomAttributeData.MaxMarshalInteger) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, arguments.Attribute.AttributeClass, namedArg.Key); hasErrors = true; } break; case "SafeArrayUserDefinedSubType": elementTypeSymbol = namedArg.Value.DecodeValue <ITypeSymbol>(SpecialType.None); symbolIndex = position; break; case "ArraySubType": case "SizeConst": case "SizeParamIndex": messageProvider.ReportParameterNotValidForType(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position); hasErrors = true; break; // other parameters ignored with no error } position++; } switch (elementTypeVariant) { case VarEnum.VT_DISPATCH: case VarEnum.VT_UNKNOWN: case VarEnum.VT_RECORD: // only these variants accept specification of user defined subtype break; default: if (elementTypeVariant != null && symbolIndex >= 0) { messageProvider.ReportParameterNotValidForType(arguments.Diagnostics, arguments.AttributeSyntaxOpt, symbolIndex); hasErrors = true; } else { // type ignored: elementTypeSymbol = null; } break; } if (!hasErrors) { arguments.GetOrCreateData <TWellKnownAttributeData>().GetOrCreateData().SetMarshalAsSafeArray(elementTypeVariant, elementTypeSymbol); } }