2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Mono.Cecil / Mono.Cecil.Binary / ResourceReader.cs
blob694ecea0ca57073a289cad99520089aa83bd0402
1 //
2 // ResourceReader.cs
3 //
4 // Author:
5 // Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 namespace Mono.Cecil.Binary {
31 using System;
32 using System.IO;
33 using System.Text;
35 sealed class ResourceReader {
37 Image m_img;
38 Section m_rsrc;
39 BinaryReader m_reader;
41 public ResourceReader (Image img)
43 m_img = img;
46 public ResourceDirectoryTable Read ()
48 m_rsrc = GetResourceSection ();
49 if (m_rsrc == null)
50 return null;
52 m_reader = new BinaryReader (new MemoryStream (m_rsrc.Data));
53 return ReadDirectoryTable ();
56 Section GetResourceSection ()
58 foreach (Section s in m_img.Sections)
59 if (s.Name == Section.Resources)
60 return s;
62 return null;
65 int GetOffset ()
67 return (int) m_reader.BaseStream.Position;
70 ResourceDirectoryTable ReadDirectoryTable ()
72 ResourceDirectoryTable rdt = new ResourceDirectoryTable (GetOffset ());
73 rdt.Characteristics = m_reader.ReadUInt32 ();
74 rdt.TimeDateStamp = m_reader.ReadUInt32 ();
75 rdt.MajorVersion = m_reader.ReadUInt16 ();
76 rdt.MinorVersion = m_reader.ReadUInt16 ();
77 ushort nameEntries = m_reader.ReadUInt16 ();
78 ushort idEntries = m_reader.ReadUInt16 ();
80 for (int i = 0; i < nameEntries; i++)
81 rdt.Entries.Add (ReadDirectoryEntry ());
83 for (int i = 0; i < idEntries; i++)
84 rdt.Entries.Add (ReadDirectoryEntry ());
86 return rdt;
89 ResourceDirectoryEntry ReadDirectoryEntry ()
91 uint name = m_reader.ReadUInt32 ();
92 uint child = m_reader.ReadUInt32 ();
94 ResourceDirectoryEntry rde;
95 if ((name & 0x80000000) != 0)
96 rde = new ResourceDirectoryEntry (ReadDirectoryString ((int) name & 0x7fffffff), GetOffset ());
97 else
98 rde = new ResourceDirectoryEntry ((int) name & 0x7fffffff, GetOffset ());
100 long pos = m_reader.BaseStream.Position;
101 m_reader.BaseStream.Position = child & 0x7fffffff;
103 if ((child & 0x80000000) != 0)
104 rde.Child = ReadDirectoryTable ();
105 else
106 rde.Child = ReadDataEntry ();
108 m_reader.BaseStream.Position = pos;
110 return rde;
113 ResourceDirectoryString ReadDirectoryString (int offset)
115 long pos = m_reader.BaseStream.Position;
116 m_reader.BaseStream.Position = offset;
118 byte [] str = m_reader.ReadBytes (m_reader.ReadUInt16 ());
120 ResourceDirectoryString rds = new ResourceDirectoryString (
121 Encoding.Unicode.GetString (str, 0, str.Length),
122 GetOffset ());
124 m_reader.BaseStream.Position = pos;
126 return rds;
129 ResourceNode ReadDataEntry ()
131 ResourceDataEntry rde = new ResourceDataEntry (GetOffset ());
132 rde.Data = m_reader.ReadUInt32 ();
133 rde.Size = m_reader.ReadUInt32 ();
134 rde.Codepage = m_reader.ReadUInt32 ();
135 rde.Reserved = m_reader.ReadUInt32 ();
137 Section sect = m_img.GetSectionAtVirtualAddress (rde.Data);
138 byte [] data = new byte [rde.Size];
139 Buffer.BlockCopy (sect.Data, (int)(long)(rde.Data - sect.VirtualAddress), data, 0, (int)rde.Size);
140 rde.ResourceData = data;
142 return rde;