112 lines
4.4 KiB
C#
112 lines
4.4 KiB
C#
// dnlib: See LICENSE.txt for more info
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace dnlib.DotNet.Writer {
|
|
/// <summary>
|
|
/// Writes <c>DeclSecurity</c> blobs
|
|
/// </summary>
|
|
public readonly struct DeclSecurityWriter : ICustomAttributeWriterHelper {
|
|
readonly ModuleDef module;
|
|
readonly IWriterError helper;
|
|
readonly DataWriterContext context;
|
|
readonly bool optimizeCustomAttributeSerializedTypeNames;
|
|
|
|
/// <summary>
|
|
/// Creates a <c>DeclSecurity</c> blob from <paramref name="secAttrs"/>
|
|
/// </summary>
|
|
/// <param name="module">Owner module</param>
|
|
/// <param name="secAttrs">List of <see cref="SecurityAttribute"/>s</param>
|
|
/// <param name="helper">Helps this class</param>
|
|
/// <returns>A <c>DeclSecurity</c> blob</returns>
|
|
public static byte[] Write(ModuleDef module, IList<SecurityAttribute> secAttrs, IWriterError helper) =>
|
|
Write(module, secAttrs, helper, false);
|
|
|
|
/// <summary>
|
|
/// Creates a <c>DeclSecurity</c> blob from <paramref name="secAttrs"/>
|
|
/// </summary>
|
|
/// <param name="module">Owner module</param>
|
|
/// <param name="secAttrs">List of <see cref="SecurityAttribute"/>s</param>
|
|
/// <param name="helper">Helps this class</param>
|
|
/// <param name="optimizeCustomAttributeSerializedTypeNames">Optimize serialized type strings in custom attributes.
|
|
/// For more info, see <see cref="MetadataFlags.OptimizeCustomAttributeSerializedTypeNames"/></param>
|
|
/// <returns>A <c>DeclSecurity</c> blob</returns>
|
|
public static byte[] Write(ModuleDef module, IList<SecurityAttribute> secAttrs, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames) =>
|
|
new DeclSecurityWriter(module, helper, optimizeCustomAttributeSerializedTypeNames, null).Write(secAttrs);
|
|
|
|
internal static byte[] Write(ModuleDef module, IList<SecurityAttribute> secAttrs, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames, DataWriterContext context) =>
|
|
new DeclSecurityWriter(module, helper, optimizeCustomAttributeSerializedTypeNames, context).Write(secAttrs);
|
|
|
|
DeclSecurityWriter(ModuleDef module, IWriterError helper, bool optimizeCustomAttributeSerializedTypeNames, DataWriterContext context) {
|
|
this.module = module;
|
|
this.helper = helper;
|
|
this.context = context;
|
|
this.optimizeCustomAttributeSerializedTypeNames = optimizeCustomAttributeSerializedTypeNames;
|
|
}
|
|
|
|
byte[] Write(IList<SecurityAttribute> secAttrs) {
|
|
if (secAttrs is null)
|
|
secAttrs = Array2.Empty<SecurityAttribute>();
|
|
|
|
var xml = DeclSecurity.GetNet1xXmlStringInternal(secAttrs);
|
|
if (xml is not null)
|
|
return WriteFormat1(xml);
|
|
return WriteFormat2(secAttrs);
|
|
}
|
|
|
|
byte[] WriteFormat1(string xml) => Encoding.Unicode.GetBytes(xml);
|
|
|
|
byte[] WriteFormat2(IList<SecurityAttribute> secAttrs) {
|
|
var sb = new StringBuilder();
|
|
var stream = new MemoryStream();
|
|
var writer = new DataWriter(stream);
|
|
writer.WriteByte((byte)'.');
|
|
WriteCompressedUInt32(writer, (uint)secAttrs.Count);
|
|
|
|
int count = secAttrs.Count;
|
|
for (int i = 0; i < count; i++) {
|
|
var sa = secAttrs[i];
|
|
if (sa is null) {
|
|
helper.Error("SecurityAttribute is null");
|
|
Write(writer, UTF8String.Empty);
|
|
WriteCompressedUInt32(writer, 1);
|
|
WriteCompressedUInt32(writer, 0);
|
|
continue;
|
|
}
|
|
var attrType = sa.AttributeType;
|
|
string fqn;
|
|
if (attrType is null) {
|
|
helper.Error("SecurityAttribute attribute type is null");
|
|
fqn = string.Empty;
|
|
}
|
|
else {
|
|
sb.Length = 0;
|
|
fqn = FullNameFactory.AssemblyQualifiedName(attrType, null, sb);
|
|
}
|
|
Write(writer, fqn);
|
|
|
|
var namedArgsBlob = context is null ?
|
|
CustomAttributeWriter.Write(this, sa.NamedArguments) :
|
|
CustomAttributeWriter.Write(this, sa.NamedArguments, context);
|
|
if (namedArgsBlob.Length > 0x1FFFFFFF) {
|
|
helper.Error("Named arguments blob size doesn't fit in 29 bits");
|
|
namedArgsBlob = Array2.Empty<byte>();
|
|
}
|
|
WriteCompressedUInt32(writer, (uint)namedArgsBlob.Length);
|
|
writer.WriteBytes(namedArgsBlob);
|
|
}
|
|
|
|
return stream.ToArray();
|
|
}
|
|
|
|
uint WriteCompressedUInt32(DataWriter writer, uint value) => writer.WriteCompressedUInt32(helper, value);
|
|
void Write(DataWriter writer, UTF8String s) => writer.Write(helper, s);
|
|
void IWriterError.Error(string message) => helper.Error(message);
|
|
bool IFullNameFactoryHelper.MustUseAssemblyName(IType type) =>
|
|
FullNameFactory.MustUseAssemblyName(module, type, optimizeCustomAttributeSerializedTypeNames);
|
|
}
|
|
}
|