2 Copyright (C) 2008 Jeroen Frijters
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
25 using System.Globalization;
26 using IKVM.Reflection.Emit;
28 namespace IKVM.Reflection.Writer
30 sealed class VersionInfo
32 private AssemblyName name;
33 private string fileName;
34 internal string copyright;
35 internal string trademark;
36 internal string product;
37 internal string company;
38 private string description;
40 internal string informationalVersion;
41 private string fileVersion;
43 internal void SetName(AssemblyName name)
48 internal void SetFileName(string assemblyFileName)
50 this.fileName = assemblyFileName;
53 internal void SetAttribute(CustomAttributeBuilder cab)
55 Universe u = cab.Constructor.Module.universe;
56 Type type = cab.Constructor.DeclaringType;
57 if (copyright == null && type == u.System_Reflection_AssemblyCopyrightAttribute)
59 copyright = (string)cab.GetConstructorArgument(0);
61 else if (trademark == null && type == u.System_Reflection_AssemblyTrademarkAttribute)
63 trademark = (string)cab.GetConstructorArgument(0);
65 else if (product == null && type == u.System_Reflection_AssemblyProductAttribute)
67 product = (string)cab.GetConstructorArgument(0);
69 else if (company == null && type == u.System_Reflection_AssemblyCompanyAttribute)
71 company = (string)cab.GetConstructorArgument(0);
73 else if (description == null && type == u.System_Reflection_AssemblyDescriptionAttribute)
75 description = (string)cab.GetConstructorArgument(0);
77 else if (title == null && type == u.System_Reflection_AssemblyTitleAttribute)
79 title = (string)cab.GetConstructorArgument(0);
81 else if (informationalVersion == null && type == u.System_Reflection_AssemblyInformationalVersionAttribute)
83 informationalVersion = (string)cab.GetConstructorArgument(0);
85 else if (fileVersion == null && type == u.System_Reflection_AssemblyFileVersionAttribute)
87 fileVersion = (string)cab.GetConstructorArgument(0);
91 internal void Write(ByteBuffer bb)
93 if (fileVersion == null)
95 if (name.Version != null)
97 fileVersion = name.Version.ToString();
101 fileVersion = "0.0.0.0";
105 int codepage = 1200; // Unicode codepage
109 if (name.CultureInfo != null)
111 lcid = name.CultureInfo.LCID;
114 catch (ArgumentException)
116 // AssemblyName.CultureInfo throws an ArgumentException if AssemblyBuilder.__SetAssemblyCulture() was used to specify a non-existing culture
119 Version filever = ParseVersionRobust(fileVersion);
120 int fileVersionMajor = filever.Major;
121 int fileVersionMinor = filever.Minor;
122 int fileVersionBuild = filever.Build;
123 int fileVersionRevision = filever.Revision;
125 int productVersionMajor = fileVersionMajor;
126 int productVersionMinor = fileVersionMinor;
127 int productVersionBuild = fileVersionBuild;
128 int productVersionRevision = fileVersionRevision;
129 if (informationalVersion != null)
131 Version productver = ParseVersionRobust(informationalVersion);
132 productVersionMajor = productver.Major;
133 productVersionMinor = productver.Minor;
134 productVersionBuild = productver.Build;
135 productVersionRevision = productver.Revision;
138 ByteBuffer stringTable = new ByteBuffer(512);
139 stringTable.Write((short)0); // wLength (placeholder)
140 stringTable.Write((short)0); // wValueLength
141 stringTable.Write((short)1); // wType
142 WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage));
143 stringTable.Align(4);
145 WriteString(stringTable, "Comments", description);
146 WriteString(stringTable, "CompanyName", company);
147 WriteString(stringTable, "FileDescription", title);
148 WriteString(stringTable, "FileVersion", fileVersion);
149 WriteString(stringTable, "InternalName", name.Name);
150 WriteString(stringTable, "LegalCopyright", copyright);
151 WriteString(stringTable, "LegalTrademarks", trademark);
152 WriteString(stringTable, "OriginalFilename", fileName);
153 WriteString(stringTable, "ProductName", product);
154 WriteString(stringTable, "ProductVersion", informationalVersion);
156 stringTable.Position = 0;
157 stringTable.Write((short)stringTable.Length);
159 ByteBuffer stringFileInfo = new ByteBuffer(512);
160 stringFileInfo.Write((short)0); // wLength (placeholder)
161 stringFileInfo.Write((short)0); // wValueLength
162 stringFileInfo.Write((short)1); // wType
163 WriteUTF16Z(stringFileInfo, "StringFileInfo");
164 stringFileInfo.Align(4);
165 stringFileInfo.Write(stringTable);
166 stringFileInfo.Position = 0;
167 stringFileInfo.Write((short)stringFileInfo.Length);
169 byte[] preamble1 = new byte[] {
170 // VS_VERSIONINFO (platform SDK)
171 0x34, 0x00, // wValueLength
173 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, // "VS_VERSION_INFO\0"
174 0x00, 0x00, // Padding1 (32 bit alignment)
175 // VS_FIXEDFILEINFO starts
176 0xBD, 0x04, 0xEF, 0xFE, // dwSignature (0xFEEF04BD)
177 0x00, 0x00, 0x01, 0x00, // dwStrucVersion
179 byte[] preamble2 = new byte[] {
180 0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??)
181 0x00, 0x00, 0x00, 0x00, // dwFileFlags (??)
182 0x04, 0x00, 0x00, 0x00, // dwFileOS
183 0x02, 0x00, 0x00, 0x00, // dwFileType
184 0x00, 0x00, 0x00, 0x00, // dwFileSubtype
185 0x00, 0x00, 0x00, 0x00, // dwFileDateMS
186 0x00, 0x00, 0x00, 0x00, // dwFileDateLS
187 // Padding2 (32 bit alignment)
189 0x44, 0x00, // wLength
190 0x00, 0x00, // wValueLength
192 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, // "VarFileInfo\0"
193 0x00, 0x00, // Padding
195 0x24, 0x00, // wLength
196 0x04, 0x00, // wValueLength
198 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, // "Translation\0"
199 0x00, 0x00, // Padding (32 bit alignment)
201 bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length));
203 bb.Write((short)fileVersionMinor);
204 bb.Write((short)fileVersionMajor);
205 bb.Write((short)fileVersionRevision);
206 bb.Write((short)fileVersionBuild);
207 bb.Write((short)productVersionMinor);
208 bb.Write((short)productVersionMajor);
209 bb.Write((short)productVersionRevision);
210 bb.Write((short)productVersionBuild);
212 bb.Write((short)lcid);
213 bb.Write((short)codepage);
214 bb.Write(stringFileInfo);
217 private static void WriteUTF16Z(ByteBuffer bb, string str)
219 foreach (char c in str)
226 private static void WriteString(ByteBuffer bb, string name, string value)
228 value = value ?? " ";
229 int pos = bb.Position;
230 bb.Write((short)0); // wLength (placeholder)
231 bb.Write((short)(value.Length + 1));// wValueLength
232 bb.Write((short)1); // wType
233 WriteUTF16Z(bb, name);
235 WriteUTF16Z(bb, value);
237 int savedPos = bb.Position;
239 bb.Write((short)(savedPos - pos));
240 bb.Position = savedPos;
243 private static Version ParseVersionRobust(string ver)
246 ushort major = ParseVersionPart(ver, ref index);
247 ushort minor = ParseVersionPart(ver, ref index);
248 ushort build = ParseVersionPart(ver, ref index);
249 ushort revision = ParseVersionPart(ver, ref index);
250 return new Version(major, minor, build, revision);
253 private static ushort ParseVersionPart(string str, ref int pos)
256 while (pos < str.Length)
264 else if (c >= '0' && c <= '9')
267 value += (ushort)(c - '0');