示例#1
0
 private static void WriteUTF16Z(ByteBuffer bb, string str)
 {
     foreach (char c in str)
     {
         bb.Write((short)c);
     }
     bb.Write((short)0);
 }
示例#2
0
 private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
 {
     WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable);
     if (Data == null)
     {
         bb.Write(0x80000000U | (uint)offset);
     }
     else
     {
         bb.Write(offset);
     }
     offset += 16 + entries.Count * 8;
 }
        private static void WriteString(ByteBuffer bb, string name, string value)
        {
            value = value ?? " ";
            int pos = bb.Position;

            bb.Write((short)0);                  // wLength (placeholder)
            bb.Write((short)(value.Length + 1)); // wValueLength
            bb.Write((short)1);                  // wType
            WriteUTF16Z(bb, name);
            bb.Align(4);
            WriteUTF16Z(bb, value);
            bb.Align(4);
            int savedPos = bb.Position;

            bb.Position = pos;
            bb.Write((short)(savedPos - pos));
            bb.Position = savedPos;
        }
示例#4
0
 internal void Write(MetadataWriter mw, uint rva)
 {
     foreach (int offset in linkOffsets)
     {
         bb.Position = offset;
         bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva);
     }
     mw.Write(bb);
 }
示例#5
0
 private void WriteResourceDataEntries(ByteBuffer bb, List <int> linkOffsets, ref int offset)
 {
     foreach (ResourceDirectoryEntry entry in entries)
     {
         if (entry.Data != null)
         {
             linkOffsets.Add(bb.Position);
             bb.Write(offset);
             bb.Write(entry.Data.Length);
             bb.Write(0);                        // code page
             bb.Write(0);                        // reserved
             offset += (entry.Data.Length + 3) & ~3;
         }
         else
         {
             entry.WriteResourceDataEntries(bb, linkOffsets, ref offset);
         }
     }
 }
		private void SetDataAndRvaImpl(byte[] data, ByteBuffer bb, int readonlyMarker)
		{
			attribs |= FieldAttributes.HasFieldRVA;
			FieldRVATable.Record rec = new FieldRVATable.Record();
			bb.Align(8);
			rec.RVA = bb.Position + readonlyMarker;
			rec.Field = pseudoToken;
			typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec);
			bb.Write(data);
		}
示例#7
0
        private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
        {
            SHA1Managed hash = new SHA1Managed();

            using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
            {
                stream.Seek(0, SeekOrigin.Begin);
                byte[] buf = new byte[8192];
                HashChunk(stream, cs, buf, (int)headerLength);
                stream.Seek(textSectionFileOffset, SeekOrigin.Begin);
                HashChunk(stream, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset));
                stream.Seek(strongNameSignatureLength, SeekOrigin.Current);
                HashChunk(stream, cs, buf, (int)(stream.Length - (strongNameSignatureFileOffset + strongNameSignatureLength)));
            }
            using (RSA rsa = CryptoHack.CreateRSA(keyPair))
            {
                RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa);
                byte[] signature = sign.CreateSignature(hash);
                Array.Reverse(signature);
                if (signature.Length != strongNameSignatureLength)
                {
                    throw new InvalidOperationException("Signature length mismatch");
                }
                stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
                stream.Write(signature, 0, signature.Length);
            }

            // compute the PE checksum
            stream.Seek(0, SeekOrigin.Begin);
            int          count = (int)stream.Length / 4;
            BinaryReader br    = new BinaryReader(stream);
            long         sum   = 0;

            for (int i = 0; i < count; i++)
            {
                sum += br.ReadUInt32();
                int carry = (int)(sum >> 32);
                sum &= 0xFFFFFFFFU;
                sum += carry;
            }
            while ((sum >> 16) != 0)
            {
                sum = (sum & 0xFFFF) + (sum >> 16);
            }
            sum += stream.Length;

            // write the PE checksum, note that it is always at offset 0xD8 in the file
            ByteBuffer bb = new ByteBuffer(4);

            bb.Write((int)sum);
            stream.Seek(0xD8, SeekOrigin.Begin);
            bb.WriteTo(stream);
        }
示例#8
0
 private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
 {
     if (currentDepth == writeDepth)
     {
         // directory header
         bb.Write(0);                    // Characteristics
         bb.Write(0);                    // Time/Date Stamp
         bb.Write(0);                    // Version (Major / Minor)
         bb.Write((ushort)namedEntries);
         bb.Write((ushort)(entries.Count - namedEntries));
     }
     foreach (ResourceDirectoryEntry entry in entries)
     {
         if (currentDepth == writeDepth)
         {
             entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable);
         }
         else
         {
             entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable);
         }
     }
 }
示例#9
0
 private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
 {
     if (id.Name == null)
     {
         bb.Write((int)id.Ordinal);
     }
     else
     {
         int stringOffset;
         if (!strings.TryGetValue(id.Name, out stringOffset))
         {
             stringOffset = stringTableOffset;
             strings.Add(id.Name, stringOffset);
             stringTableOffset += id.Name.Length * 2 + 2;
             stringTable.Write((ushort)id.Name.Length);
             foreach (char c in id.Name)
             {
                 stringTable.Write((short)c);
             }
         }
         bb.Write(0x80000000U | (uint)stringOffset);
     }
 }
示例#10
0
 private void WriteData(ByteBuffer bb)
 {
     foreach (ResourceDirectoryEntry entry in entries)
     {
         if (entry.Data != null)
         {
             bb.Write(entry.Data);
             bb.Align(4);
         }
         else
         {
             entry.WriteData(bb);
         }
     }
 }
示例#11
0
        private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
        {
            byte[] hash;
            using (SHA1 sha1 = SHA1.Create())
            {
                stream.Seek(0, SeekOrigin.Begin);
                Stream skipStream = new SkipStream(stream, strongNameSignatureFileOffset, strongNameSignatureLength);
                skipStream = new SkipStream(skipStream, headerLength, textSectionFileOffset - headerLength);
                hash       = sha1.ComputeHash(skipStream);
            }
            using (RSACryptoServiceProvider rsa = keyPair.CreateRSA())
            {
                byte[] signature = rsa.SignHash(hash, "1.3.14.3.2.26");
                Array.Reverse(signature);
                if (signature.Length != strongNameSignatureLength)
                {
                    throw new InvalidOperationException("Signature length mismatch");
                }
                stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
                stream.Write(signature, 0, signature.Length);
            }

            // compute the PE checksum
            stream.Seek(0, SeekOrigin.Begin);
            int          count = (int)stream.Length / 4;
            BinaryReader br    = new BinaryReader(stream);
            long         sum   = 0;

            for (int i = 0; i < count; i++)
            {
                sum += br.ReadUInt32();
                int carry = (int)(sum >> 32);
                sum &= 0xFFFFFFFFU;
                sum += carry;
            }
            while ((sum >> 16) != 0)
            {
                sum = (sum & 0xFFFF) + (sum >> 16);
            }
            sum += stream.Length;

            // write the PE checksum, note that it is always at offset 0xD8 in the file
            ByteBuffer bb = new ByteBuffer(4);

            bb.Write((int)sum);
            stream.Seek(0xD8, SeekOrigin.Begin);
            bb.WriteTo(stream);
        }
示例#12
0
 internal void Write(ByteBuffer bb, List <int> linkOffsets)
 {
     if (entries.Count != 0)
     {
         int stringTableOffset            = this.DirectoryLength;
         Dictionary <string, int> strings = new Dictionary <string, int>();
         ByteBuffer stringTable           = new ByteBuffer(16);
         int        offset = 16 + entries.Count * 8;
         for (int pass = 0; pass < 3; pass++)
         {
             Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable);
         }
         // the pecoff spec says that the string table is between the directory entries and the data entries,
         // but the windows linker puts them after the data entries, so we do too.
         stringTable.Align(4);
         offset += stringTable.Length;
         WriteResourceDataEntries(bb, linkOffsets, ref offset);
         bb.Write(stringTable);
         WriteData(bb);
     }
 }
示例#13
0
		private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount)
		{
			byte first;
			if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
			{
				Debug.Assert(genericParamCount == 0);
				first = VARARG;
			}
			else if (genericParamCount > 0)
			{
				first = GENERIC;
			}
			else
			{
				first = DEFAULT;
			}
			if ((callingConvention & CallingConventions.HasThis) != 0)
			{
				first |= HASTHIS;
			}
			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
			{
				first |= EXPLICITTHIS;
			}
			bb.Write(first);
			if (genericParamCount > 0)
			{
				bb.WriteCompressedInt(genericParamCount);
			}
			bb.WriteCompressedInt(parameterCount);
			// RetType
			if (modifiers != null && modifiers[0] != null)
			{
				WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[0][0]);
				WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[0][1]);
			}
			WriteType(module, bb, returnType);
			// Param
			for (int i = 0; i < parameterTypes.Length; i++)
			{
				if (modifiers != null && modifiers[i + 1] != null)
				{
					WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[i + 1][0]);
					WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[i + 1][1]);
				}
				WriteType(module, bb, parameterTypes[i]);
			}
		}
		private static void WriteString(ByteBuffer bb, string str)
		{
			byte[] buf = Encoding.UTF8.GetBytes(str);
			bb.WriteCompressedUInt(buf.Length);
			bb.Write(buf);
		}
示例#15
0
		private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
		{
			if (id.Name == null)
			{
				bb.Write((int)id.Ordinal);
			}
			else
			{
				int stringOffset;
				if (!strings.TryGetValue(id.Name, out stringOffset))
				{
					stringOffset = stringTableOffset;
					strings.Add(id.Name, stringOffset);
					stringTableOffset += id.Name.Length * 2 + 2;
					stringTable.Write((ushort)id.Name.Length);
					foreach (char c in id.Name)
					{
						stringTable.Write((short)c);
					}
				}
				bb.Write(0x80000000U | (uint)stringOffset);
			}
		}
示例#16
0
		private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
		{
			if (currentDepth == writeDepth)
			{
				// directory header
				bb.Write(0);	// Characteristics
				bb.Write(0);	// Time/Date Stamp
				bb.Write(0);	// Version (Major / Minor)
				bb.Write((ushort)namedEntries);
				bb.Write((ushort)(entries.Count - namedEntries));
			}
			foreach (ResourceDirectoryEntry entry in entries)
			{
				if (currentDepth == writeDepth)
				{
					entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable);
				}
				else
				{
					entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable);
				}
			}
		}
示例#17
0
		private void WriteResourceDataEntries(ByteBuffer bb, List<int> linkOffsets, ref int offset)
		{
			foreach (ResourceDirectoryEntry entry in entries)
			{
				if (entry.Data != null)
				{
					linkOffsets.Add(bb.Position);
					bb.Write(offset);
					bb.Write(entry.Data.Length);
					bb.Write(0);	// code page
					bb.Write(0);	// reserved
					offset += (entry.Data.Length + 3) & ~3;
				}
				else
				{
					entry.WriteResourceDataEntries(bb, linkOffsets, ref offset);
				}
			}
		}
示例#18
0
文件: Heaps.cs 项目: djbhau/TraceLab
 internal BlobHeap()
 {
     buf.Write((byte)0);
 }
		internal static void WriteMethodSpec(ModuleBuilder module, ByteBuffer bb, Type[] genArgs)
		{
			bb.Write(GENERICINST);
			bb.WriteCompressedUInt(genArgs.Length);
			foreach (Type arg in genArgs)
			{
				WriteType(module, bb, arg);
			}
		}
示例#20
0
文件: Signature.cs 项目: koush/mono
		protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type)
		{
			while (type.HasElementType)
			{
				if (type.__IsVector)
				{
					bb.Write(ELEMENT_TYPE_SZARRAY);
				}
				else if (type.IsArray)
				{
					int rank = type.GetArrayRank();
					bb.Write(ELEMENT_TYPE_ARRAY);
					// LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it
					WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
					WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
					WriteType(module, bb, type.GetElementType());
					bb.WriteCompressedInt(rank);
					// since a Type doesn't contain the lower/upper bounds
					// (they act like a custom modifier, so they are part of the signature, but not of the Type),
					// we set them to the C# compatible values and hope for the best
					bb.WriteCompressedInt(0);	// boundsCount
					bb.WriteCompressedInt(rank);	// loCount
					for (int i = 0; i < rank; i++)
					{
						bb.WriteCompressedInt(0);
					}
					return;
				}
				else if (type.IsByRef)
				{
					bb.Write(ELEMENT_TYPE_BYREF);
				}
				else if (type.IsPointer)
				{
					bb.Write(ELEMENT_TYPE_PTR);
				}
				WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers());
				WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers());
				type = type.GetElementType();
			}
			Universe u = module.universe;
			if (type == u.System_Void)
			{
				bb.Write(ELEMENT_TYPE_VOID);
			}
			else if (type == u.System_Int32)
			{
				bb.Write(ELEMENT_TYPE_I4);
			}
			else if (type == u.System_Boolean)
			{
				bb.Write(ELEMENT_TYPE_BOOLEAN);
			}
			else if (type == u.System_String)
			{
				bb.Write(ELEMENT_TYPE_STRING);
			}
			else if (type == u.System_Char)
			{
				bb.Write(ELEMENT_TYPE_CHAR);
			}
			else if (type == u.System_SByte)
			{
				bb.Write(ELEMENT_TYPE_I1);
			}
			else if (type == u.System_Byte)
			{
				bb.Write(ELEMENT_TYPE_U1);
			}
			else if (type == u.System_Int16)
			{
				bb.Write(ELEMENT_TYPE_I2);
			}
			else if (type == u.System_UInt16)
			{
				bb.Write(ELEMENT_TYPE_U2);
			}
			else if (type == u.System_UInt32)
			{
				bb.Write(ELEMENT_TYPE_U4);
			}
			else if (type == u.System_Int64)
			{
				bb.Write(ELEMENT_TYPE_I8);
			}
			else if (type == u.System_UInt64)
			{
				bb.Write(ELEMENT_TYPE_U8);
			}
			else if (type == u.System_Single)
			{
				bb.Write(ELEMENT_TYPE_R4);
			}
			else if (type == u.System_Double)
			{
				bb.Write(ELEMENT_TYPE_R8);
			}
			else if (type == u.System_IntPtr)
			{
				bb.Write(ELEMENT_TYPE_I);
			}
			else if (type == u.System_UIntPtr)
			{
				bb.Write(ELEMENT_TYPE_U);
			}
			else if (type == u.System_TypedReference)
			{
				bb.Write(ELEMENT_TYPE_TYPEDBYREF);
			}
			else if (type == u.System_Object)
			{
				bb.Write(ELEMENT_TYPE_OBJECT);
			}
			else if (type.IsGenericParameter)
			{
				if (type is UnboundGenericMethodParameter || type.DeclaringMethod != null)
				{
					bb.Write(ELEMENT_TYPE_MVAR);
				}
				else
				{
					bb.Write(ELEMENT_TYPE_VAR);
				}
				bb.WriteCompressedInt(type.GenericParameterPosition);
			}
			else if (type.IsGenericType)
			{
				WriteGenericSignature(module, bb, type);
			}
			else
			{
				if (type.IsValueType)
				{
					bb.Write(ELEMENT_TYPE_VALUETYPE);
				}
				else
				{
					bb.Write(ELEMENT_TYPE_CLASS);
				}
				bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
			}
		}
示例#21
0
文件: Signature.cs 项目: koush/mono
		protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, byte mod, Type[] modifiers)
		{
			if (modifiers != null)
			{
				foreach (Type type in modifiers)
				{
					bb.Write(mod);
					bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(type));
				}
			}
		}
示例#22
0
文件: Signature.cs 项目: koush/mono
		// unmanaged calling convention
		internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConvention callingConvention, Type returnType, Type[] parameterTypes)
		{
			switch (callingConvention)
			{
				case CallingConvention.Cdecl:
					bb.Write((byte)0x01);	// C
					break;
				case CallingConvention.StdCall:
				case CallingConvention.Winapi:
					bb.Write((byte)0x02);	// STDCALL
					break;
				case CallingConvention.ThisCall:
					bb.Write((byte)0x03);	// THISCALL
					break;
				case CallingConvention.FastCall:
					bb.Write((byte)0x04);	// FASTCALL
					break;
				default:
					throw new ArgumentOutOfRangeException("callingConvention");
			}
			bb.WriteCompressedInt(parameterTypes.Length);
			WriteType(module, bb, returnType);
			foreach (Type t in parameterTypes)
			{
				WriteType(module, bb, t);
			}
		}
示例#23
0
文件: Signature.cs 项目: koush/mono
		// managed calling convention
		internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
		{
			byte flags = 0;
			if ((callingConvention & CallingConventions.HasThis) != 0)
			{
				flags |= HASTHIS;
			}
			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
			{
				flags |= EXPLICITTHIS;
			}
			if ((callingConvention & CallingConventions.VarArgs) != 0)
			{
				flags |= VARARG;
			}
			bb.Write(flags);
			bb.WriteCompressedInt(parameterTypes.Length + optionalParameterTypes.Length);
			WriteType(module, bb, returnType);
			foreach (Type t in parameterTypes)
			{
				WriteType(module, bb, t);
			}
			if (optionalParameterTypes.Length > 0)
			{
				bb.Write(SENTINEL);
				foreach (Type t in optionalParameterTypes)
				{
					WriteType(module, bb, t);
				}
			}
		}
示例#24
0
文件: Signature.cs 项目: koush/mono
		internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals)
		{
			bb.Write(LOCAL_SIG);
			bb.WriteCompressedInt(locals.Count);
			foreach (LocalBuilder local in locals)
			{
				if (local.IsPinned)
				{
					bb.Write(ELEMENT_TYPE_PINNED);
				}
				WriteType(module, bb, local.LocalType);
			}
		}
示例#25
0
文件: Signature.cs 项目: koush/mono
		internal static void WritePropertySig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention,
			Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
			Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
		{
			byte flags = PROPERTY;
			if ((callingConvention & CallingConventions.HasThis) != 0)
			{
				flags |= HASTHIS;
			}
			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
			{
				flags |= EXPLICITTHIS;
			}
			if ((callingConvention & CallingConventions.VarArgs) != 0)
			{
				flags |= VARARG;
			}
			bb.Write(flags);
			bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
			WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, returnTypeRequiredCustomModifiers);
			WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, returnTypeOptionalCustomModifiers);
			WriteType(module, bb, returnType);
			if (parameterTypes != null)
			{
				for (int i = 0; i < parameterTypes.Length; i++)
				{
					if (parameterTypeRequiredCustomModifiers != null)
					{
						WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterTypeRequiredCustomModifiers[i]);
					}
					if (parameterTypeOptionalCustomModifiers != null)
					{
						WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterTypeOptionalCustomModifiers[i]);
					}
					WriteType(module, bb, parameterTypes[i]);
				}
			}
		}
示例#26
0
        internal void AddIcon(byte[] iconFile)
        {
            BinaryReader br         = new BinaryReader(new MemoryStream(iconFile));
            ushort       idReserved = br.ReadUInt16();
            ushort       idType     = br.ReadUInt16();
            ushort       idCount    = br.ReadUInt16();

            if (idReserved != 0 || idType != 1)
            {
                throw new ArgumentException("The supplied byte array is not a valid .ico file.");
            }
            ByteBuffer group = new ByteBuffer(6 + 14 * idCount);

            group.Write(idReserved);
            group.Write(idType);
            group.Write(idCount);
            for (int i = 0; i < idCount; i++)
            {
                byte   bWidth        = br.ReadByte();
                byte   bHeight       = br.ReadByte();
                byte   bColorCount   = br.ReadByte();
                byte   bReserved     = br.ReadByte();
                ushort wPlanes       = br.ReadUInt16();
                ushort wBitCount     = br.ReadUInt16();
                uint   dwBytesInRes  = br.ReadUInt32();
                uint   dwImageOffset = br.ReadUInt32();

                // we start the icon IDs at 2
                ushort id = (ushort)(2 + i);

                group.Write(bWidth);
                group.Write(bHeight);
                group.Write(bColorCount);
                group.Write(bReserved);
                group.Write(wPlanes);
                group.Write(wBitCount);
                group.Write(dwBytesInRes);
                group.Write(id);

                byte[] icon = new byte[dwBytesInRes];
                Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length);
                root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon);
            }
            root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group;
        }
		internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, __StandAloneMethodSig sig)
		{
			if (sig.IsUnmanaged)
			{
				switch (sig.UnmanagedCallingConvention)
				{
					case CallingConvention.Cdecl:
						bb.Write((byte)0x01);	// C
						break;
					case CallingConvention.StdCall:
					case CallingConvention.Winapi:
						bb.Write((byte)0x02);	// STDCALL
						break;
					case CallingConvention.ThisCall:
						bb.Write((byte)0x03);	// THISCALL
						break;
					case CallingConvention.FastCall:
						bb.Write((byte)0x04);	// FASTCALL
						break;
					default:
						throw new ArgumentOutOfRangeException("callingConvention");
				}
			}
			else
			{
				CallingConventions callingConvention = sig.CallingConvention;
				byte flags = 0;
				if ((callingConvention & CallingConventions.HasThis) != 0)
				{
					flags |= HASTHIS;
				}
				if ((callingConvention & CallingConventions.ExplicitThis) != 0)
				{
					flags |= EXPLICITTHIS;
				}
				if ((callingConvention & CallingConventions.VarArgs) != 0)
				{
					flags |= VARARG;
				}
				bb.Write(flags);
			}
			Type[] parameterTypes = sig.ParameterTypes;
			Type[] optionalParameterTypes = sig.OptionalParameterTypes;
			bb.WriteCompressedUInt(parameterTypes.Length + optionalParameterTypes.Length);
			WriteCustomModifiers(module, bb, sig.GetReturnTypeCustomModifiers());
			WriteType(module, bb, sig.ReturnType);
			int index = 0;
			foreach (Type t in parameterTypes)
			{
				WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++));
				WriteType(module, bb, t);
			}
			// note that optional parameters are only allowed for managed signatures (but we don't enforce that)
			if (optionalParameterTypes.Length > 0)
			{
				bb.Write(SENTINEL);
				foreach (Type t in optionalParameterTypes)
				{
					WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++));
					WriteType(module, bb, t);
				}
			}
		}
		private static void WriteUTF16Z(ByteBuffer bb, string str)
		{
			foreach (char c in str)
			{
				bb.Write((short)c);
			}
			bb.Write((short)0);
		}
		internal static void WriteSignatureHelper(ModuleBuilder module, ByteBuffer bb, byte flags, ushort paramCount, List<Type> args)
		{
			bb.Write(flags);
			if (flags != FIELD)
			{
				bb.WriteCompressedUInt(paramCount);
			}
			foreach (Type type in args)
			{
				if (type == null)
				{
					bb.Write(ELEMENT_TYPE_VOID);
				}
				else if (type is MarkerType)
				{
					bb.Write(type.SigElementType);
				}
				else
				{
					WriteType(module, bb, type);
				}
			}
		}
示例#30
0
		private static void StrongName(FileStream fs, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
		{
			SHA1Managed hash = new SHA1Managed();
			using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
			{
				fs.Seek(0, SeekOrigin.Begin);
				byte[] buf = new byte[8192];
				HashChunk(fs, cs, buf, (int)headerLength);
				fs.Seek(textSectionFileOffset, SeekOrigin.Begin);
				HashChunk(fs, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset));
				fs.Seek(strongNameSignatureLength, SeekOrigin.Current);
				HashChunk(fs, cs, buf, (int)(fs.Length - (strongNameSignatureFileOffset + strongNameSignatureLength)));
			}
			using (RSA rsa = CryptoHack.CreateRSA(keyPair))
			{
				RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa);
				sign.SetHashAlgorithm("SHA1");
				byte[] signature = sign.CreateSignature(hash.Hash);
				Array.Reverse(signature);
				Debug.Assert(signature.Length == strongNameSignatureLength);
				fs.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
				fs.Write(signature, 0, signature.Length);
			}

			// compute the PE checksum
			fs.Seek(0, SeekOrigin.Begin);
			int count = (int)fs.Length / 4;
			BinaryReader br = new BinaryReader(fs);
			long sum = 0;
			for (int i = 0; i < count; i++)
			{
				sum += br.ReadUInt32();
				int carry = (int)(sum >> 32);
				sum &= 0xFFFFFFFFU;
				sum += carry;
			}
			while ((sum >> 16) != 0)
			{
				sum = (sum & 0xFFFF) + (sum >> 16);
			}
			sum += fs.Length;

			// write the PE checksum, note that it is always at offset 0xD8 in the file
			ByteBuffer bb = new ByteBuffer(4);
			bb.Write((int)sum);
			fs.Seek(0xD8, SeekOrigin.Begin);
			bb.WriteTo(fs);
		}
示例#31
0
		internal void Write(ByteBuffer bb, List<int> linkOffsets)
		{
			if (entries.Count != 0)
			{
				int stringTableOffset = this.DirectoryLength;
				Dictionary<string, int> strings = new Dictionary<string, int>();
				ByteBuffer stringTable = new ByteBuffer(16);
				int offset = 16 + entries.Count * 8;
				for (int pass = 0; pass < 3; pass++)
				{
					Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable);
				}
				// the pecoff spec says that the string table is between the directory entries and the data entries,
				// but the windows linker puts them after the data entries, so we do too.
				stringTable.Align(4);
				offset += stringTable.Length;
				WriteResourceDataEntries(bb, linkOffsets, ref offset);
				bb.Write(stringTable);
				WriteData(bb);
			}
		}
示例#32
0
		internal override void WriteSig(ModuleBuilder module, ByteBuffer bb)
		{
			byte flags = PROPERTY;
			if ((callingConvention & CallingConventions.HasThis) != 0)
			{
				flags |= HASTHIS;
			}
			if ((callingConvention & CallingConventions.ExplicitThis) != 0)
			{
				flags |= EXPLICITTHIS;
			}
			if ((callingConvention & CallingConventions.VarArgs) != 0)
			{
				flags |= VARARG;
			}
			bb.Write(flags);
			bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length);
			WriteCustomModifiers(module, bb, customModifiers.GetReturnTypeCustomModifiers());
			WriteType(module, bb, propertyType);
			if (parameterTypes != null)
			{
				for (int i = 0; i < parameterTypes.Length; i++)
				{
					WriteCustomModifiers(module, bb, customModifiers.GetParameterCustomModifiers(i));
					WriteType(module, bb, parameterTypes[i]);
				}
			}
		}
示例#33
0
		private void WriteData(ByteBuffer bb)
		{
			foreach (ResourceDirectoryEntry entry in entries)
			{
				if (entry.Data != null)
				{
					bb.Write(entry.Data);
					bb.Align(4);
				}
				else
				{
					entry.WriteData(bb);
				}
			}
		}
		internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers)
		{
			WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
			if (optionalParameterTypes.Length > 0)
			{
				bb.Write(SENTINEL);
				for (int i = 0; i < optionalParameterTypes.Length; i++)
				{
					WriteCustomModifiers(module, bb, Util.NullSafeElementAt(customModifiers, i));
					WriteType(module, bb, optionalParameterTypes[i]);
				}
			}
		}
示例#35
0
		private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable)
		{
			WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable);
			if (Data == null)
			{
				bb.Write(0x80000000U | (uint)offset);
			}
			else
			{
				bb.Write(offset);
			}
			offset += 16 + entries.Count * 8;
		}
		protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type)
		{
			while (type.HasElementType)
			{
				byte sigElementType = type.SigElementType;
				bb.Write(sigElementType);
				if (sigElementType == ELEMENT_TYPE_ARRAY)
				{
					// LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it
					WriteCustomModifiers(module, bb, type.__GetCustomModifiers());
					WriteType(module, bb, type.GetElementType());
					bb.WriteCompressedUInt(type.GetArrayRank());
					int[] sizes = type.__GetArraySizes();
					bb.WriteCompressedUInt(sizes.Length);
					for (int i = 0; i < sizes.Length; i++)
					{
						bb.WriteCompressedUInt(sizes[i]);
					}
					int[] lobounds = type.__GetArrayLowerBounds();
					bb.WriteCompressedUInt(lobounds.Length);
					for (int i = 0; i < lobounds.Length; i++)
					{
						bb.WriteCompressedInt(lobounds[i]);
					}
					return;
				}
				WriteCustomModifiers(module, bb, type.__GetCustomModifiers());
				type = type.GetElementType();
			}
			if (type.__IsBuiltIn)
			{
				bb.Write(type.SigElementType);
			}
			else if (type.IsGenericParameter)
			{
				bb.Write(type.SigElementType);
				bb.WriteCompressedUInt(type.GenericParameterPosition);
			}
			else if (!type.__IsMissing && type.IsGenericType)
			{
				WriteGenericSignature(module, bb, type);
			}
			else if (type.__IsFunctionPointer)
			{
				bb.Write(ELEMENT_TYPE_FNPTR);
				WriteStandAloneMethodSig(module, bb, type.__MethodSignature);
			}
			else
			{
				if (type.IsValueType)
				{
					bb.Write(ELEMENT_TYPE_VALUETYPE);
				}
				else
				{
					bb.Write(ELEMENT_TYPE_CLASS);
				}
				bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
			}
		}
示例#37
0
		internal void AddIcon(byte[] iconFile)
		{
			BinaryReader br = new BinaryReader(new MemoryStream(iconFile));
			ushort idReserved = br.ReadUInt16();
			ushort idType = br.ReadUInt16();
			ushort idCount = br.ReadUInt16();
			if (idReserved != 0 || idType != 1)
			{
				throw new ArgumentException("The supplied byte array is not a valid .ico file.");
			}
			ByteBuffer group = new ByteBuffer(6 + 14 * idCount);
			group.Write(idReserved);
			group.Write(idType);
			group.Write(idCount);
			for (int i = 0; i < idCount; i++)
			{
				byte bWidth = br.ReadByte();
				byte bHeight = br.ReadByte();
				byte bColorCount = br.ReadByte();
				byte bReserved = br.ReadByte();
				ushort wPlanes = br.ReadUInt16();
				ushort wBitCount = br.ReadUInt16();
				uint dwBytesInRes = br.ReadUInt32();
				uint dwImageOffset = br.ReadUInt32();

				// we start the icon IDs at 2
				ushort id = (ushort)(2 + i);

				group.Write(bWidth);
				group.Write(bHeight);
				group.Write(bColorCount);
				group.Write(bReserved);
				group.Write(wPlanes);
				group.Write(wBitCount);
				group.Write(dwBytesInRes);
				group.Write(id);

				byte[] icon = new byte[dwBytesInRes];
				Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length);
				root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon);
			}
			root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group;
		}
		private static void WriteGenericSignature(ModuleBuilder module, ByteBuffer bb, Type type)
		{
			Type[] typeArguments = type.GetGenericArguments();
			CustomModifiers[] customModifiers = type.__GetGenericArgumentsCustomModifiers();
			if (!type.IsGenericTypeDefinition)
			{
				type = type.GetGenericTypeDefinition();
			}
			bb.Write(ELEMENT_TYPE_GENERICINST);
			if (type.IsValueType)
			{
				bb.Write(ELEMENT_TYPE_VALUETYPE);
			}
			else
			{
				bb.Write(ELEMENT_TYPE_CLASS);
			}
			bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token);
			bb.WriteCompressedUInt(typeArguments.Length);
			for (int i = 0; i < typeArguments.Length; i++)
			{
				WriteCustomModifiers(module, bb, customModifiers[i]);
				WriteType(module, bb, typeArguments[i]);
			}
		}
示例#39
0
		internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes)
		{
			WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length);
			if (optionalParameterTypes.Length > 0)
			{
				bb.Write(SENTINEL);
				foreach (Type type in optionalParameterTypes)
				{
					WriteType(module, bb, type);
				}
			}
		}
		protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, CustomModifiers modifiers)
		{
			foreach (CustomModifiers.Entry entry in modifiers)
			{
				bb.Write(entry.IsRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT);
				bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(entry.Type));
			}
		}
		private static void WriteString(ByteBuffer bb, string name, string value)
		{
			value = value ?? " ";
			int pos = bb.Position;
			bb.Write((short)0);					// wLength (placeholder)
			bb.Write((short)(value.Length + 1));// wValueLength
			bb.Write((short)1);					// wType
			WriteUTF16Z(bb, name);
			bb.Align(4);
			WriteUTF16Z(bb, value);
			bb.Align(4);
			int savedPos = bb.Position;
			bb.Position = pos;
			bb.Write((short)(savedPos - pos));
			bb.Position = savedPos;
		}
		private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength)
		{
			SHA1Managed hash = new SHA1Managed();
			using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write))
			{
				stream.Seek(0, SeekOrigin.Begin);
				byte[] buf = new byte[8192];
				HashChunk(stream, cs, buf, (int)headerLength);
				stream.Seek(textSectionFileOffset, SeekOrigin.Begin);
				HashChunk(stream, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset));
				stream.Seek(strongNameSignatureLength, SeekOrigin.Current);
				HashChunk(stream, cs, buf, (int)(stream.Length - (strongNameSignatureFileOffset + strongNameSignatureLength)));
			}
			using (RSA rsa = keyPair.CreateRSA())
			{
				RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa);
				byte[] signature = sign.CreateSignature(hash);
				Array.Reverse(signature);
				if (signature.Length != strongNameSignatureLength)
				{
					throw new InvalidOperationException("Signature length mismatch");
				}
				stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin);
				stream.Write(signature, 0, signature.Length);
			}

			// compute the PE checksum
			stream.Seek(0, SeekOrigin.Begin);
			int count = (int)stream.Length / 4;
			BinaryReader br = new BinaryReader(stream);
			long sum = 0;
			for (int i = 0; i < count; i++)
			{
				sum += br.ReadUInt32();
				int carry = (int)(sum >> 32);
				sum &= 0xFFFFFFFFU;
				sum += carry;
			}
			while ((sum >> 16) != 0)
			{
				sum = (sum & 0xFFFF) + (sum >> 16);
			}
			sum += stream.Length;

			// write the PE checksum, note that it is always at offset 0xD8 in the file
			ByteBuffer bb = new ByteBuffer(4);
			bb.Write((int)sum);
			stream.Seek(0xD8, SeekOrigin.Begin);
			bb.WriteTo(stream);
		}
        internal void Write(ByteBuffer bb)
        {
            if (fileVersion == null)
            {
                if (name.Version != null)
                {
                    fileVersion = name.Version.ToString();
                }
                else
                {
                    fileVersion = "0.0.0.0";
                }
            }

            int codepage = 1200; // Unicode codepage
            int lcid     = 0x7f;

            if (name.CultureInfo != null)
            {
                lcid = name.CultureInfo.LCID;
            }
            if (culture != null)
            {
                lcid = new CultureInfo(culture).LCID;
            }

            Version filever             = ParseVersionRobust(fileVersion);
            int     fileVersionMajor    = filever.Major;
            int     fileVersionMinor    = filever.Minor;
            int     fileVersionBuild    = filever.Build;
            int     fileVersionRevision = filever.Revision;

            int productVersionMajor    = fileVersionMajor;
            int productVersionMinor    = fileVersionMinor;
            int productVersionBuild    = fileVersionBuild;
            int productVersionRevision = fileVersionRevision;

            if (informationalVersion != null)
            {
                Version productver = ParseVersionRobust(informationalVersion);
                productVersionMajor    = productver.Major;
                productVersionMinor    = productver.Minor;
                productVersionBuild    = productver.Build;
                productVersionRevision = productver.Revision;
            }

            ByteBuffer stringTable = new ByteBuffer(512);

            stringTable.Write((short)0); // wLength (placeholder)
            stringTable.Write((short)0); // wValueLength
            stringTable.Write((short)1); // wType
            WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage));
            stringTable.Align(4);

            WriteString(stringTable, "Comments", description);
            WriteString(stringTable, "CompanyName", company);
            WriteString(stringTable, "FileDescription", title);
            WriteString(stringTable, "FileVersion", fileVersion);
            WriteString(stringTable, "InternalName", name.Name);
            WriteString(stringTable, "LegalCopyright", copyright);
            WriteString(stringTable, "LegalTrademarks", trademark);
            WriteString(stringTable, "OriginalFilename", fileName);
            WriteString(stringTable, "ProductName", product);
            WriteString(stringTable, "ProductVersion", informationalVersion);

            stringTable.Position = 0;
            stringTable.Write((short)stringTable.Length);

            ByteBuffer stringFileInfo = new ByteBuffer(512);

            stringFileInfo.Write((short)0); // wLength (placeholder)
            stringFileInfo.Write((short)0); // wValueLength
            stringFileInfo.Write((short)1); // wType
            WriteUTF16Z(stringFileInfo, "StringFileInfo");
            stringFileInfo.Align(4);
            stringFileInfo.Write(stringTable);
            stringFileInfo.Position = 0;
            stringFileInfo.Write((short)stringFileInfo.Length);

            byte[] preamble1 = new byte[]
            {
                // VS_VERSIONINFO (platform SDK)
                0x34, 0x00,                                                                                                                                                                                     // wValueLength
                0x00, 0x00,                                                                                                                                                                                     // wType
                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"
                0x00, 0x00,                                                                                                                                                                                     // Padding1 (32 bit alignment)
                // VS_FIXEDFILEINFO starts
                0xBD, 0x04, 0xEF, 0xFE,                                                                                                                                                                         // dwSignature (0xFEEF04BD)
                0x00, 0x00, 0x01, 0x00,                                                                                                                                                                         // dwStrucVersion
            };
            byte[] preamble2 = new byte[]
            {
                0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??)
                0x00, 0x00, 0x00, 0x00, // dwFileFlags (??)
                0x04, 0x00, 0x00, 0x00, // dwFileOS
                0x02, 0x00, 0x00, 0x00, // dwFileType
                0x00, 0x00, 0x00, 0x00, // dwFileSubtype
                0x00, 0x00, 0x00, 0x00, // dwFileDateMS
                0x00, 0x00, 0x00, 0x00, // dwFileDateLS
                // Padding2 (32 bit alignment)
                // VarFileInfo
                0x44, 0x00,                                                                                                                                     // wLength
                0x00, 0x00,                                                                                                                                     // wValueLength
                0x01, 0x00,                                                                                                                                     // wType
                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"
                0x00, 0x00,                                                                                                                                     // Padding
                // Var
                0x24, 0x00,                                                                                                                                     // wLength
                0x04, 0x00,                                                                                                                                     // wValueLength
                0x00, 0x00,                                                                                                                                     // wType
                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"
                0x00, 0x00,                                                                                                                                     // Padding (32 bit alignment)
            };
            bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length));
            bb.Write(preamble1);
            bb.Write((short)fileVersionMinor);
            bb.Write((short)fileVersionMajor);
            bb.Write((short)fileVersionRevision);
            bb.Write((short)fileVersionBuild);
            bb.Write((short)productVersionMinor);
            bb.Write((short)productVersionMajor);
            bb.Write((short)productVersionRevision);
            bb.Write((short)productVersionBuild);
            bb.Write(preamble2);
            bb.Write((short)lcid);
            bb.Write((short)codepage);
            bb.Write(stringFileInfo);
        }
		internal void Write(ByteBuffer bb)
		{
			if (fileVersion == null)
			{
				if (name.Version != null)
				{
					fileVersion = name.Version.ToString();
				}
				else
				{
					fileVersion = "0.0.0.0";
				}
			}

			int codepage = 1200;	// Unicode codepage
			int lcid = 0x7f;
			try
			{
				if (name.CultureInfo != null)
				{
					lcid = name.CultureInfo.LCID;
				}
			}
			catch (ArgumentException)
			{
				// AssemblyName.CultureInfo throws an ArgumentException if AssemblyBuilder.__SetAssemblyCulture() was used to specify a non-existing culture
			}

			Version filever = ParseVersionRobust(fileVersion);
			int fileVersionMajor = filever.Major;
			int fileVersionMinor = filever.Minor;
			int fileVersionBuild = filever.Build;
			int fileVersionRevision = filever.Revision;

			int productVersionMajor = fileVersionMajor;
			int productVersionMinor = fileVersionMinor;
			int productVersionBuild = fileVersionBuild;
			int productVersionRevision = fileVersionRevision;
			if (informationalVersion != null)
			{
				Version productver = ParseVersionRobust(informationalVersion);
				productVersionMajor = productver.Major;
				productVersionMinor = productver.Minor;
				productVersionBuild = productver.Build;
				productVersionRevision = productver.Revision;
			}

			ByteBuffer stringTable = new ByteBuffer(512);
			stringTable.Write((short)0);	// wLength (placeholder)
			stringTable.Write((short)0);	// wValueLength
			stringTable.Write((short)1);	// wType
			WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage));
			stringTable.Align(4);

			WriteString(stringTable, "Comments", description);
			WriteString(stringTable, "CompanyName", company);
			WriteString(stringTable, "FileDescription", title);
			WriteString(stringTable, "FileVersion", fileVersion);
			WriteString(stringTable, "InternalName", name.Name);
			WriteString(stringTable, "LegalCopyright", copyright);
			WriteString(stringTable, "LegalTrademarks", trademark);
			WriteString(stringTable, "OriginalFilename", fileName);
			WriteString(stringTable, "ProductName", product);
			WriteString(stringTable, "ProductVersion", informationalVersion);

			stringTable.Position = 0;
			stringTable.Write((short)stringTable.Length);

			ByteBuffer stringFileInfo = new ByteBuffer(512);
			stringFileInfo.Write((short)0);	// wLength (placeholder)
			stringFileInfo.Write((short)0);	// wValueLength
			stringFileInfo.Write((short)1);	// wType
			WriteUTF16Z(stringFileInfo, "StringFileInfo");
			stringFileInfo.Align(4);
			stringFileInfo.Write(stringTable);
			stringFileInfo.Position = 0;
			stringFileInfo.Write((short)stringFileInfo.Length);

			byte[] preamble1 = new byte[] {
			  // VS_VERSIONINFO (platform SDK)
			  0x34, 0x00,				// wValueLength
			  0x00, 0x00,				// wType
			  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"
			  0x00, 0x00,				// Padding1 (32 bit alignment)
			  // VS_FIXEDFILEINFO starts
			  0xBD, 0x04, 0xEF, 0xFE,	// dwSignature (0xFEEF04BD)
			  0x00, 0x00, 0x01, 0x00,	// dwStrucVersion
			};
			byte[] preamble2 = new byte[] {
			  0x3F, 0x00, 0x00, 0x00,	// dwFileFlagsMask (??)
			  0x00, 0x00, 0x00, 0x00,	// dwFileFlags (??)
			  0x04, 0x00, 0x00, 0x00,	// dwFileOS
			  0x02, 0x00, 0x00, 0x00,	// dwFileType
			  0x00, 0x00, 0x00, 0x00,	// dwFileSubtype
			  0x00, 0x00, 0x00, 0x00,	// dwFileDateMS
			  0x00, 0x00, 0x00, 0x00,	// dwFileDateLS
										// Padding2 (32 bit alignment)
			  // VarFileInfo
			  0x44, 0x00,				// wLength
			  0x00, 0x00,				// wValueLength
			  0x01, 0x00,				// wType
			  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"
			  0x00, 0x00,				// Padding
			  // Var
			  0x24, 0x00,				// wLength
			  0x04, 0x00,				// wValueLength
			  0x00, 0x00,				// wType
			  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"
			  0x00, 0x00,				// Padding (32 bit alignment)
			};
			bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length));
			bb.Write(preamble1);
			bb.Write((short)fileVersionMinor);
			bb.Write((short)fileVersionMajor);
			bb.Write((short)fileVersionRevision);
			bb.Write((short)fileVersionBuild);
			bb.Write((short)productVersionMinor);
			bb.Write((short)productVersionMajor);
			bb.Write((short)productVersionRevision);
			bb.Write((short)productVersionBuild);
			bb.Write(preamble2);
			bb.Write((short)lcid);
			bb.Write((short)codepage);
			bb.Write(stringFileInfo);
		}