PEResourceClasses.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * PERWAPI - An API for Reading and Writing PE Files
  3. *
  4. * Copyright (c) Diane Corney, Queensland University of Technology, 2004.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the PERWAPI Copyright as included with this
  8. * distribution in the file PERWAPIcopyright.rtf.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY as is explained in the copyright notice.
  12. *
  13. * The author may be contacted at d.corney@qut.edu.au
  14. *
  15. * Version Date: 26/01/07
  16. */
  17. using System;
  18. using System.IO;
  19. using System.Collections;
  20. namespace QUT.PERWAPI
  21. {
  22. public abstract class PEResourceElement
  23. {
  24. private int id;
  25. private string name;
  26. public PEResourceElement() { }
  27. public int Id
  28. {
  29. get { return id; }
  30. set { id = value; }
  31. }
  32. public string Name
  33. {
  34. get { return name; }
  35. set { name = value; }
  36. }
  37. protected internal abstract uint Size();
  38. protected internal abstract void Write(BinaryWriter dest, uint RVA);
  39. }
  40. public class PEResourceDirectory : PEResourceElement
  41. {
  42. public PEResourceDirectory() { }
  43. private uint date = 0;
  44. private ushort majver = 1;
  45. private ushort minver = 0;
  46. public uint Date { get { return date; } set { date = value; } }
  47. public ushort MajVer { get { return majver; } set { majver = value; } }
  48. public ushort MinVer { get { return minver; } set { minver = value; } }
  49. private ArrayList subitems = new ArrayList();
  50. public PEResourceElement this[int i] { get { return (PEResourceElement)subitems[i]; } }
  51. public int Count() { return subitems.Count; }
  52. public bool HasData()
  53. {
  54. return subitems.Count > 0;
  55. }
  56. public void AddElement(PEResourceElement el)
  57. {
  58. subitems.Add(el);
  59. }
  60. private uint subsize, namesize, dirsize, numnamed;
  61. protected internal override uint Size()
  62. {
  63. namesize = 0;
  64. numnamed = 0;
  65. subsize = 0;
  66. for (int i = 0; i < subitems.Count; i++)
  67. {
  68. PEResourceElement el = (PEResourceElement)subitems[i];
  69. subsize += el.Size();
  70. if (el.Name != null)
  71. {
  72. namesize += 2 + (uint)el.Name.Length * 2;
  73. numnamed++;
  74. }
  75. }
  76. dirsize = (uint)subitems.Count * 8 + 16;
  77. return dirsize + namesize + subsize;
  78. }
  79. protected internal override void Write(BinaryWriter dest, uint RVA)
  80. {
  81. Size();
  82. dest.Flush();
  83. uint startnameoffset = (uint)dest.BaseStream.Position + (uint)dirsize;
  84. uint curritemoffset = startnameoffset + (uint)namesize;
  85. dest.Write((uint)0); // characteristics
  86. dest.Write(date); // datetime
  87. dest.Write(majver);
  88. dest.Write(minver);
  89. dest.Write((ushort)numnamed);
  90. dest.Write((ushort)(subitems.Count - numnamed));
  91. uint currnameoffset = startnameoffset;
  92. for (int i = 0; i < subitems.Count; i++)
  93. {
  94. PEResourceElement el = (PEResourceElement)subitems[i];
  95. if (el.Name != null)
  96. {
  97. dest.Write((uint)(currnameoffset | 0x80000000));
  98. if (el is PEResourceDirectory)
  99. dest.Write((uint)(curritemoffset | 0x80000000));
  100. else
  101. dest.Write((uint)curritemoffset);
  102. currnameoffset += 2 + (uint)el.Name.Length * 2;
  103. }
  104. curritemoffset += el.Size();
  105. }
  106. curritemoffset = startnameoffset + namesize;
  107. for (int i = 0; i < subitems.Count; i++)
  108. {
  109. PEResourceElement el = (PEResourceElement)subitems[i];
  110. if (el.Name == null)
  111. {
  112. dest.Write(el.Id);
  113. if (el is PEResourceDirectory)
  114. dest.Write((uint)(curritemoffset | 0x80000000));
  115. else
  116. dest.Write((uint)curritemoffset);
  117. }
  118. curritemoffset += el.Size();
  119. }
  120. for (int i = 0; i < subitems.Count; i++)
  121. {
  122. PEResourceElement el = (PEResourceElement)subitems[i];
  123. string s = el.Name;
  124. if (s != null)
  125. {
  126. dest.Write((ushort)s.Length);
  127. byte[] b = System.Text.Encoding.Unicode.GetBytes(s);
  128. dest.Write(b);
  129. }
  130. }
  131. for (int i = 0; i < subitems.Count; i++)
  132. {
  133. PEResourceElement el = (PEResourceElement)subitems[i];
  134. el.Write(dest, RVA);
  135. }
  136. }
  137. }
  138. public class PEResourceData : PEResourceElement
  139. {
  140. public PEResourceData() { }
  141. int codepage = 0;
  142. byte[] data;
  143. public int CodePage { get { return codepage; } set { codepage = value; } }
  144. public byte[] Data { get { return data; } set { data = value; } }
  145. protected internal override uint Size()
  146. {
  147. return 16 + (uint)Data.Length;
  148. }
  149. protected internal override void Write(BinaryWriter dest, uint RVA)
  150. {
  151. dest.Flush();
  152. dest.Write((uint)(dest.BaseStream.Position + 16) + RVA);
  153. dest.Write((uint)data.Length);
  154. dest.Write((uint)codepage);
  155. dest.Write((uint)0);
  156. dest.Write(data);
  157. }
  158. }
  159. }