using Mono.Security;
using Mono.Security.Cryptography;
-namespace System.Reflection.Emit {
+namespace System.Reflection.Emit
+{
+ internal enum NativeResourceType
+ {
+ None,
+ Unmanaged,
+ Assembly,
+ Explicit
+ }
internal struct RefEmitPermissionSet {
public SecurityAction action;
bool created;
bool is_module_only;
private Mono.Security.StrongName sn;
+ NativeResourceType native_resource;
readonly bool is_compiler_context;
+ string versioninfo_culture;
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void basic_init (AssemblyBuilder ab);
/* Set defaults from n */
if (n.CultureInfo != null) {
culture = n.CultureInfo.Name;
+ versioninfo_culture = n.CultureInfo.Name;
}
Version v = n.Version;
if (v != null) {
{
if (resource == null)
throw new ArgumentNullException ("resource");
+ if (native_resource != NativeResourceType.None)
+ throw new ArgumentException ("Native resource has already been defined.");
+
+ // avoid definition of more than one unmanaged resource
+ native_resource = NativeResourceType.Unmanaged;
/*
* The format of the argument byte array is not documented
throw new ArgumentException ("resourceFileName");
if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
+ if (native_resource != NativeResourceType.None)
+ throw new ArgumentException ("Native resource has already been defined.");
+
+ // avoid definition of more than one unmanaged resource
+ native_resource = NativeResourceType.Unmanaged;
using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
Win32ResFileReader reader = new Win32ResFileReader (fs);
public void DefineVersionInfoResource ()
{
- if (version_res != null)
+ if (native_resource != NativeResourceType.None)
throw new ArgumentException ("Native resource has already been defined.");
- version_res = new Win32VersionResource (1, 0);
+ // avoid definition of more than one unmanaged resource
+ native_resource = NativeResourceType.Assembly;
- if (cattrs != null) {
- foreach (CustomAttributeBuilder cb in cattrs) {
- string attrname = cb.Ctor.ReflectedType.FullName;
-
- if (attrname == "System.Reflection.AssemblyProductAttribute")
- version_res.ProductName = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
- version_res.CompanyName = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
- version_res.LegalCopyright = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
- version_res.LegalTrademarks = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyCultureAttribute"){
- int lcid;
-
- try {
- lcid = new CultureInfo (GetCultureString (cb.string_arg ())).LCID;
- } catch (ArgumentException){
- //
- // This means that the resource is set to the invariant, but
- // the locale encoded will come from the AssemblyName anyways.
- //
- // In fact, my exploration of MS.NEt shows that this is always
- // set to zero, so I wonder if we should completely drop this
- // code from here.
- //
- lcid = CultureInfo.InvariantCulture.LCID;
- }
- version_res.FileLanguage = lcid;
- }
- else if (attrname == "System.Reflection.AssemblyFileVersionAttribute")
- version_res.FileVersion = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
- version_res.ProductVersion = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyTitleAttribute")
- version_res.FileDescription = cb.string_arg ();
- else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
- version_res.Comments = cb.string_arg ();
- }
- }
+ version_res = new Win32VersionResource (1, 0, IsCompilerContext);
}
public void DefineVersionInfoResource (string product, string productVersion,
string company, string copyright, string trademark)
{
- if (version_res != null)
+ if (native_resource != NativeResourceType.None)
throw new ArgumentException ("Native resource has already been defined.");
+ // avoid definition of more than one unmanaged resource
+ native_resource = NativeResourceType.Explicit;
+
/*
* We can only create the resource later, when the file name and
* the binary version is known.
*/
- version_res = new Win32VersionResource (1, 0);
+ version_res = new Win32VersionResource (1, 0, false);
version_res.ProductName = product != null ? product : " ";
version_res.ProductVersion = productVersion != null ? productVersion : " ";
version_res.CompanyName = company != null ? company : " ";
}
}
- private void DefineVersionInfoResourceImpl (string fileName) {
- // Add missing info
- if (version_res.Version == "0.0.0.0")
- version_res.Version = version;
- if (version_res.FileVersion.Trim ().Length == 0 && version != null)
- version_res.FileVersion = version;
- version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
+ private void DefineVersionInfoResourceImpl (string fileName)
+ {
+ if (versioninfo_culture != null)
+ version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
+ version_res.Version = version == null ? "0.0.0.0" : version;
+
+ if (cattrs != null) {
+ switch (native_resource) {
+ case NativeResourceType.Assembly:
+ foreach (CustomAttributeBuilder cb in cattrs) {
+ string attrname = cb.Ctor.ReflectedType.FullName;
+
+ if (attrname == "System.Reflection.AssemblyProductAttribute")
+ version_res.ProductName = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
+ version_res.CompanyName = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
+ version_res.LegalCopyright = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
+ version_res.LegalTrademarks = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
+ if (!IsCompilerContext)
+ version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
+ } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
+ string fileversion = cb.string_arg ();
+ if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
+ version_res.FileVersion = fileversion;
+ } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
+ version_res.ProductVersion = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyTitleAttribute")
+ version_res.FileDescription = cb.string_arg ();
+ else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
+ version_res.Comments = cb.string_arg ();
+ }
+ break;
+ case NativeResourceType.Explicit:
+ foreach (CustomAttributeBuilder cb in cattrs) {
+ string attrname = cb.Ctor.ReflectedType.FullName;
+
+ if (attrname == "System.Reflection.AssemblyCultureAttribute") {
+ if (!IsCompilerContext)
+ version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
+ } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
+ version_res.Comments = cb.string_arg ();
+ }
+ break;
+ }
+ }
+
version_res.OriginalFilename = fileName;
+ if (IsCompilerContext) {
+ version_res.InternalName = fileName;
+ if (version_res.ProductVersion.Trim ().Length == 0)
+ version_res.ProductVersion = version_res.FileVersion;
+ } else {
+ version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
+ }
+
AddUnmanagedResource (version_res);
}
+2008-03-29 Gert Driesen <drieseng@users.sourceforge.net>
+
+ * AssemblyBuilder.cs: Added enum that determines the type of the
+ native (version) resource. Added fields for holding the native
+ resource type and the version culture. The versioninfo_culture was
+ introduced to hold the original culture of the assembly, since
+ the AssemblyCultureAttribute should only affect the language of the
+ versioninfo block when not used in compiler context. Move constructin
+ of native version info to DefineVersionInfoResourceImpl to allow
+ attributes to affect the versioninfo after DefineVersionInfoResource
+ has been invoked. Allow ArgumentException for invalid culture string
+ to bubble up. In compiler context, use FileVersion as default value
+ for ProductionVersion.
+
2008-03-14 Zoltan Varga <vargaz@gmail.com>
* FieldOnTypeBuilderInst.cs: New file.
+2008-03-29 Gert Driesen <drieseng@users.sourceforge.net>
+
+ * Win32Resources.cs: On 2.0 profile, initiale fixed info to zero-length
+ string when emitting versioninfo in compiler context. Default to
+ neutral language in compiler context. On 1.0 profile, use 0xffff as
+ default value for version parts. In Version, abort on first invalid
+ version part and also set FileVersion string. In ProductVersion and
+ FileVersion, parse version string and abort on first invalid version
+ part.
+
2008-03-15 Gert Driesen <drieseng@users.sourceforge.net>
* ResourceManager.cs: Default to RuntimeResourceSet for all ctors.
using System;
using System.Collections;
+using System.Globalization;
using System.IO;
using System.Text;
public string[] WellKnownProperties = {
"Comments",
"CompanyName",
+#if !NET_2_0
"FileDescription",
+#endif
"FileVersion",
"InternalName",
+#if !NET_2_0
"LegalCopyright",
+#endif
"LegalTrademarks",
"OriginalFilename",
"ProductName",
Hashtable properties;
- public Win32VersionResource (int id, int language) : base (Win32ResourceType.RT_VERSION, id, language) {
+ public Win32VersionResource (int id, int language, bool compilercontext) : base (Win32ResourceType.RT_VERSION, id, language) {
// Initialize non-public members to the usual values used in
// resources
signature = 0xfeef04bd;
file_subtype = 0;
file_date = 0;
- file_lang = 0x7f;
+ file_lang = compilercontext ? 0x00 : 0x7f;
file_codepage = 1200;
properties = new Hashtable ();
+#if NET_2_0
+ string defaultvalue = compilercontext ? string.Empty : " ";
+#else
+ string defaultvalue = " ";
+#endif
+
// Well known properties
foreach (string s in WellKnownProperties)
// The value of properties can't be empty
- properties [s] = " ";
+ properties [s] = defaultvalue;
+
+#if NET_2_0
+ LegalCopyright = " ";
+ FileDescription = " ";
+#endif
}
public string Version {
}
set {
+#if NET_2_0
long[] ver = new long [4] { 0, 0, 0, 0 };
+#else
+ long [] ver = new long [4] { 0, 0xffff, 0xffff, 0xffff };
+#endif
if (value != null) {
string[] parts = value.Split ('.');
-
- for (int i = 0; i < parts.Length; ++i) {
- try {
+
+ try {
+ for (int i = 0; i < parts.Length; ++i) {
if (i < ver.Length)
ver [i] = Int32.Parse (parts [i]);
}
- catch (FormatException) {
- }
+ } catch (FormatException) {
}
}
file_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
+ properties ["FileVersion"] = Version;
}
}
return (string)properties ["ProductVersion"];
}
set {
- properties ["ProductVersion"] = value == String.Empty ? " " : value;
+ if (value == null || value.Length == 0)
+ value = " ";
+
+ long [] ver = new long [4] { 0, 0, 0, 0 };
+
+ string [] parts = value.Split ('.');
+
+ try {
+ for (int i = 0; i < parts.Length; ++i) {
+ if (i < ver.Length)
+ ver [i] = Int32.Parse (parts [i]);
+ }
+ } catch (FormatException) {
+ }
+
+ properties ["ProductVersion"] = value;
+ product_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
}
}
}
public virtual int FileLanguage {
- get {
- return file_lang;
- }
- set {
- file_lang = value;
- }
+ get { return file_lang; }
+ set { file_lang = value; }
}
public virtual string FileVersion {
return (string)properties ["FileVersion"];
}
set {
- properties ["FileVersion"] = value == String.Empty ? " " : value;
+ if (value == null || value.Length == 0)
+ value = " ";
+
+ long[] ver = new long [4] { 0, 0, 0, 0 };
+ string[] parts = value.Split ('.');
+
+ try {
+ for (int i = 0; i < parts.Length; ++i) {
+ if (i < ver.Length)
+ ver [i] = Int32.Parse (parts [i]);
+ }
+ } catch (FormatException) {
+ }
+
+ properties ["FileVersion"] = value;
+ file_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
}
}
}
[Test] // DefineUnmanagedResource (String)
- [Category ("NotWorking")]
public void TestDefineUnmanagedResource2_ResourceAlreadyDefined ()
{
string version_res = Path.Combine (tempDir, "version.res");
}
[Test] // DefineVersionInfoResource ()
- [Category ("NotWorking")]
+ public void TestDefineVersionInfoResource1_Culture_NotSupported ()
+ {
+ AssemblyName aname = new AssemblyName ();
+ aname.CultureInfo = new CultureInfo ("nl-BE");
+ aname.Name = "lib";
+ aname.Version = new Version (3, 5, 7);
+
+ AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (
+ aname, AssemblyBuilderAccess.RunAndSave,
+ tempDir);
+
+ // AssemblyCulture
+ Type attrType = typeof (AssemblyCultureAttribute);
+ ConstructorInfo ci = attrType.GetConstructor (new Type [] { typeof (String) });
+ CustomAttributeBuilder cab = new CustomAttributeBuilder (
+ ci, new object [1] { "doesnotexist" });
+ ab.SetCustomAttribute (cab);
+
+ ab.DefineVersionInfoResource ();
+
+ try {
+ ab.Save ("lib.dll");
+ Assert.Fail ("#A1");
+ } catch (ArgumentException ex) {
+ // Culture name doesnotexist is not supported
+ Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+ Assert.IsNull (ex.InnerException, "#A3");
+ Assert.IsNotNull (ex.Message, "#A4");
+ Assert.IsTrue (ex.Message.IndexOf ("doesnotexist") != -1, "#A5");
+ Assert.AreEqual ("name", ex.ParamName, "#A6");
+ }
+
+ ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname,
+ AssemblyBuilderAccess.RunAndSave, tempDir);
+
+ // AssemblyCulture
+ attrType = typeof (AssemblyCultureAttribute);
+ ci = attrType.GetConstructor (new Type [] { typeof (String) });
+ cab = new CustomAttributeBuilder (ci, new object [1] { "neutral" });
+ ab.SetCustomAttribute (cab);
+
+ ab.DefineVersionInfoResource ();
+
+ try {
+ ab.Save ("lib.dll");
+ Assert.Fail ("#B1");
+ } catch (ArgumentException ex) {
+ // Culture name neutral is not supported
+ Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+ Assert.IsNull (ex.InnerException, "#B3");
+ Assert.IsNotNull (ex.Message, "#B4");
+ Assert.IsTrue (ex.Message.IndexOf ("neutral") != -1, "#B5");
+ Assert.AreEqual ("name", ex.ParamName, "#B6");
+ }
+ }
+
+ [Test] // DefineVersionInfoResource ()
public void TestDefineVersionInfoResource1_ResourceAlreadyDefined ()
{
string version_res = Path.Combine (tempDir, "version.res");
}
[Test] // DefineVersionInfoResource (String, String, String, String, String)
- [Category ("NotWorking")]
+ public void TestDefineVersionInfoResource2_Culture_NotSupported ()
+ {
+ AssemblyName aname = new AssemblyName ();
+ aname.CultureInfo = new CultureInfo ("nl-BE");
+ aname.Name = "lib";
+ aname.Version = new Version (3, 5, 7);
+
+ AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (
+ aname, AssemblyBuilderAccess.RunAndSave,
+ tempDir);
+
+ // AssemblyCulture
+ Type attrType = typeof (AssemblyCultureAttribute);
+ ConstructorInfo ci = attrType.GetConstructor (new Type [] { typeof (String) });
+ CustomAttributeBuilder cab = new CustomAttributeBuilder (
+ ci, new object [1] { "doesnotexist" });
+ ab.SetCustomAttribute (cab);
+
+ ab.DefineVersionInfoResource ("A", "1.0", "C", "D", "E");
+
+ try {
+ ab.Save ("lib.dll");
+ Assert.Fail ("#A1");
+ } catch (ArgumentException ex) {
+ // Culture name doesnotexist is not supported
+ Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
+ Assert.IsNull (ex.InnerException, "#A3");
+ Assert.IsNotNull (ex.Message, "#A4");
+ Assert.IsTrue (ex.Message.IndexOf ("doesnotexist") != -1, "#A5");
+ Assert.AreEqual ("name", ex.ParamName, "#A6");
+ }
+
+ ab = AppDomain.CurrentDomain.DefineDynamicAssembly (aname,
+ AssemblyBuilderAccess.RunAndSave, tempDir);
+
+ // AssemblyCulture
+ attrType = typeof (AssemblyCultureAttribute);
+ ci = attrType.GetConstructor (new Type [] { typeof (String) });
+ cab = new CustomAttributeBuilder (ci, new object [1] { "neutral" });
+ ab.SetCustomAttribute (cab);
+
+ ab.DefineVersionInfoResource ("A", "1.0", "C", "D", "E");
+
+ try {
+ ab.Save ("lib.dll");
+ Assert.Fail ("#B1");
+ } catch (ArgumentException ex) {
+ // Culture name neutral is not supported
+ Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
+ Assert.IsNull (ex.InnerException, "#B3");
+ Assert.IsNotNull (ex.Message, "#B4");
+ Assert.IsTrue (ex.Message.IndexOf ("neutral") != -1, "#B5");
+ Assert.AreEqual ("name", ex.ParamName, "#B6");
+ }
+ }
+
+ [Test] // DefineVersionInfoResource (String, String, String, String, String)
public void TestDefineVersionInfoResource2_ResourceAlreadyDefined ()
{
string version_res = Path.Combine (tempDir, "version.res");
Module[] arr;
arr = ab.GetModules ();
+ Assert.IsNotNull (arr, "#A1");
// FIXME: This doesn't work on mono
- //Assert.IsTrue (arr.Length >= 2);
+ //Assert.IsTrue (arr.Length >= 2, "#A2");
foreach (Module m in arr)
- Assert.AreEqual (typeof (ModuleBuilder), m.GetType ());
+ Assert.AreEqual (typeof (ModuleBuilder), m.GetType (), "#A3");
// Test with no modules
AssemblyBuilder ab2 = genAssembly ();
arr = ab2.GetModules ();
+ Assert.IsNotNull (arr, "#B1");
+ Assert.AreEqual (0, arr.Length, "#B2");
}
[Test]
+2008-03-29 Gert Driesen <drieseng@users.sourceforge.net>
+
+ * AssemblyBuilderTest.cs: Enabled DefineUnmanagedResource and
+ DefineVersionInfoResource tests for ArgumentException when native
+ resource is already defined. Added tests for not supported culture
+ in AssemblyCultureAttribute when definining versioninfo resource.
+
2008-03-16 Zoltan Varga <vargaz@gmail.com>
* TypeBuilderTest.cs (GetField): Add test for #351172.