/*
- Copyright (C) 2008-2011 Jeroen Frijters
+ Copyright (C) 2008-2012 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
using System.IO;
using System.Diagnostics;
using System.Globalization;
+using System.Resources;
using System.Security.Cryptography;
using System.Security;
using IKVM.Reflection.Metadata;
private PEFileKinds fileKind = PEFileKinds.Dll;
private MethodInfo entryPoint;
private VersionInfo versionInfo;
- private ResourceSection unmanagedResources;
+ private byte[] win32icon;
+ private byte[] win32manifest;
+ private byte[] win32resources;
private string imageRuntimeVersion;
internal int mdStreamVersion = 0x20000;
private Module pseudoManifestModule;
private readonly List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
private readonly List<CustomAttributeBuilder> declarativeSecurity = new List<CustomAttributeBuilder>();
private readonly List<Type> typeForwarders = new List<Type>();
- private Dictionary<ScopedTypeName, Type> missingTypes;
private struct ResourceFile
{
internal string Name;
internal string FileName;
internal ResourceAttributes Attributes;
- }
-
- private struct ScopedTypeName : IEquatable<ScopedTypeName>
- {
- private readonly Type declaringType;
- private readonly TypeName name;
-
- internal ScopedTypeName(Type declaringType, TypeName name)
- {
- this.declaringType = declaringType;
- this.name = name;
- }
-
- public override bool Equals(object obj)
- {
- ScopedTypeName? other = obj as ScopedTypeName?;
- return other != null && ((IEquatable<ScopedTypeName>)other.Value).Equals(this);
- }
-
- public override int GetHashCode()
- {
- return declaringType == null ? name.GetHashCode() : declaringType.GetHashCode() * 7 + name.GetHashCode();
- }
-
- bool IEquatable<ScopedTypeName>.Equals(ScopedTypeName other)
- {
- return other.declaringType == declaringType && other.name == name;
- }
+ internal ResourceWriter Writer;
}
internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
{
this.name = name.Name;
SetVersionHelper(name.Version);
- if (name.CultureInfo != null && !string.IsNullOrEmpty(name.CultureInfo.Name))
+ if (!string.IsNullOrEmpty(name.Culture))
{
- this.culture = name.CultureInfo.Name;
+ this.culture = name.Culture;
}
- this.flags = name.Flags;
+ this.flags = name.RawFlags;
this.hashAlgorithm = name.HashAlgorithm;
if (this.hashAlgorithm == AssemblyHashAlgorithm.None)
{
this.requiredPermissions = requiredPermissions;
this.optionalPermissions = optionalPermissions;
this.refusedPermissions = refusedPermissions;
- if (universe.HasMscorlib && universe.Mscorlib.ImageRuntimeVersion != null)
+ if (universe.HasMscorlib && !universe.Mscorlib.__IsMissing && universe.Mscorlib.ImageRuntimeVersion != null)
{
this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion;
}
}
}
+ private void Rename(AssemblyName oldName)
+ {
+ this.fullName = null;
+ universe.RenameAssembly(this, oldName);
+ }
+
public void __SetAssemblyVersion(Version version)
{
AssemblyName oldName = GetName();
SetVersionHelper(version);
- universe.RenameAssembly(this, oldName);
+ Rename(oldName);
}
public void __SetAssemblyCulture(string cultureName)
{
AssemblyName oldName = GetName();
this.culture = cultureName;
- universe.RenameAssembly(this, oldName);
+ Rename(oldName);
}
public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair)
{
this.publicKey = keyPair.PublicKey;
}
- universe.RenameAssembly(this, oldName);
+ Rename(oldName);
}
// this is used in combination with delay signing
{
AssemblyName oldName = GetName();
this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone();
- universe.RenameAssembly(this, oldName);
+ Rename(oldName);
}
public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm)
public void __SetAssemblyFlags(AssemblyNameFlags flags)
{
+ AssemblyName oldName = GetName();
this.flags = flags;
+ Rename(oldName);
+ }
+
+ public override AssemblyNameFlags __AssemblyFlags
+ {
+ get { return flags; }
+ }
+
+ internal string Name
+ {
+ get { return name; }
}
public override AssemblyName GetName()
AssemblyName n = new AssemblyName();
n.Name = name;
n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion);
- n.Culture = culture;
+ n.Culture = culture ?? "";
n.HashAlgorithm = hashAlgorithm;
- n.Flags = flags;
+ n.RawFlags = flags;
n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty<byte>.Array);
n.KeyPair = keyPair;
return n;
}
- public override string FullName
- {
- get { return GetName().FullName; }
- }
-
public override string Location
{
get { throw new NotSupportedException(); }
foreach (ModuleBuilder moduleBuilder in modules)
{
+ moduleBuilder.SetIsSaved();
moduleBuilder.PopulatePropertyAndEventTables();
if (manifestModule == null
manifestModule.AddDeclarativeSecurity(token, requestRefuse, refusedPermissions);
}
+ ResourceSection unmanagedResources = versionInfo != null || win32icon != null || win32manifest != null || win32resources != null
+ ? new ResourceSection()
+ : null;
+
if (versionInfo != null)
{
versionInfo.SetName(GetName());
}
ByteBuffer versionInfoData = new ByteBuffer(512);
versionInfo.Write(versionInfoData);
- if (unmanagedResources == null)
- {
- unmanagedResources = new ResourceSection();
- }
unmanagedResources.AddVersionInfo(versionInfoData);
}
+ if (win32icon != null)
+ {
+ unmanagedResources.AddIcon(win32icon);
+ }
+
+ if (win32manifest != null)
+ {
+ unmanagedResources.AddManifest(win32manifest, fileKind == PEFileKinds.Dll ? (ushort)2 : (ushort)1);
+ }
+
+ if (win32resources != null)
+ {
+ unmanagedResources.ExtractResources(win32resources);
+ }
+
foreach (CustomAttributeBuilder cab in customAttributes)
{
// we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
foreach (ResourceFile resfile in resourceFiles)
{
+ if (resfile.Writer != null)
+ {
+ resfile.Writer.Generate();
+ resfile.Writer.Close();
+ }
int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
rec.Offset = 0;
foreach (ModuleBuilder moduleBuilder in modules)
{
moduleBuilder.FillAssemblyRefTable();
+ moduleBuilder.EmitResources();
if (moduleBuilder != manifestModule)
{
int fileToken;
ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length);
}
}
- FileTable.Record file = new FileTable.Record();
- file.Flags = flags;
- file.Name = manifestModule.Strings.Add(Path.GetFileName(fileName));
- file.HashValue = manifestModule.Blobs.Add(ByteBuffer.Wrap(hash.Hash));
- return 0x26000000 + manifestModule.File.AddRecord(file);
+ return manifestModule.__AddModule(flags, Path.GetFileName(fileName), hash.Hash);
}
public void AddResourceFile(string name, string fileName)
resourceFiles.Add(resfile);
}
+ public IResourceWriter DefineResource(string name, string description, string fileName)
+ {
+ return DefineResource(name, description, fileName, ResourceAttributes.Public);
+ }
+
+ public IResourceWriter DefineResource(string name, string description, string fileName, ResourceAttributes attribute)
+ {
+ // FXBUG we ignore the description, because there is no such thing
+
+ string fullPath = fileName;
+ if (dir != null)
+ {
+ fullPath = Path.Combine(dir, fileName);
+ }
+ ResourceWriter rw = new ResourceWriter(fullPath);
+ ResourceFile resfile;
+ resfile.Name = name;
+ resfile.FileName = fileName;
+ resfile.Attributes = attribute;
+ resfile.Writer = rw;
+ resourceFiles.Add(resfile);
+ return rw;
+ }
+
public void DefineVersionInfoResource()
{
+ if (versionInfo != null || win32resources != null)
+ {
+ throw new ArgumentException("Native resource has already been defined.");
+ }
versionInfo = new VersionInfo();
}
public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark)
{
+ if (versionInfo != null || win32resources != null)
+ {
+ throw new ArgumentException("Native resource has already been defined.");
+ }
versionInfo = new VersionInfo();
versionInfo.product = product;
versionInfo.informationalVersion = productVersion;
public void __DefineIconResource(byte[] iconFile)
{
- unmanagedResources = new ResourceSection();
- unmanagedResources.AddIcon(iconFile);
+ if (win32icon != null || win32resources != null)
+ {
+ throw new ArgumentException("Native resource has already been defined.");
+ }
+ win32icon = (byte[])iconFile.Clone();
+ }
+
+ public void __DefineManifestResource(byte[] manifest)
+ {
+ if (win32manifest != null || win32resources != null)
+ {
+ throw new ArgumentException("Native resource has already been defined.");
+ }
+ win32manifest = (byte[])manifest.Clone();
}
public void __DefineUnmanagedResource(byte[] resource)
{
+ if (versionInfo != null || win32icon != null || win32manifest != null || win32resources != null)
+ {
+ throw new ArgumentException("Native resource has already been defined.");
+ }
// The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section,
// but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves
// like DefineUnmanagedResource(string).
- unmanagedResources = new ResourceSection();
- unmanagedResources.ExtractResources(resource);
+ win32resources = (byte[])resource.Clone();
}
public void DefineUnmanagedResource(string resourceFileName)
return null;
}
- internal override Type GetMissingType(TypeName name)
+ internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
{
- return GetMissingType(this.ManifestModule, null, name);
- }
-
- internal Type GetMissingType(Module module, Type declaringType, TypeName name)
- {
- if (missingTypes == null)
- {
- return null;
- }
- ScopedTypeName stn = new ScopedTypeName(declaringType, name);
- Type type;
- if (!missingTypes.TryGetValue(stn, out type))
+ foreach (ModuleBuilder mb in modules)
{
- type = new MissingType(module, declaringType, name.Namespace, name.Name);
- missingTypes.Add(stn, type);
+ Type type = mb.FindTypeIgnoreCase(lowerCaseName);
+ if (type != null)
+ {
+ return type;
+ }
}
- return type;
- }
-
- public void __EnableMissingTypeResolution()
- {
- if (missingTypes == null)
+ foreach (Module module in addedModules)
{
- missingTypes = new Dictionary<ScopedTypeName, Type>();
+ Type type = module.FindTypeIgnoreCase(lowerCaseName);
+ if (type != null)
+ {
+ return type;
+ }
}
+ return null;
}
public override string ImageRuntimeVersion
}
return list;
}
+
+ internal bool IsWindowsRuntime
+ {
+ get { return (flags & (AssemblyNameFlags)0x200) != 0; }
+ }
}
- sealed class ManifestModule : Module
+ sealed class ManifestModule : NonPEModule
{
private readonly AssemblyBuilder assembly;
private readonly Guid guid = Guid.NewGuid();
return null;
}
+ internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
+ {
+ return null;
+ }
+
internal override void GetTypesImpl(List<Type> list)
{
}
get { return guid; }
}
- public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
- {
- throw new ArgumentException();
- }
-
- public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
- {
- throw new ArgumentException();
- }
-
- public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
- {
- throw new ArgumentException();
- }
-
- public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
- {
- throw new ArgumentException();
- }
-
- public override string ResolveString(int metadataToken)
- {
- throw new ArgumentException();
- }
-
- public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
- {
- throw new ArgumentException();
- }
-
public override string ScopeName
{
get { return "RefEmit_InMemoryManifestModule"; }
}
- public override AssemblyName[] __GetReferencedAssemblies()
- {
- throw new InvalidOperationException();
- }
-
- internal override Type GetModuleType()
- {
- throw new InvalidOperationException();
- }
-
- internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+ protected override Exception NotSupportedException()
{
- throw new InvalidOperationException();
+ return new InvalidOperationException();
}
}
}