diff --git a/BurnOutSharp.Builder/PortableExecutable.cs b/BurnOutSharp.Builder/PortableExecutable.cs
index a25808a5..37da7031 100644
--- a/BurnOutSharp.Builder/PortableExecutable.cs
+++ b/BurnOutSharp.Builder/PortableExecutable.cs
@@ -152,7 +152,27 @@ namespace BurnOutSharp.Builder
#endregion
- // TODO: DelayLoadDirectoryTable
+ #region Delay-Load Directory Table
+
+ if (optionalHeader.DelayImportDescriptor != null && optionalHeader.DelayImportDescriptor.VirtualAddress != 0)
+ {
+ // If the offset for the delay-load directory table doesn't exist
+ int delayLoadDirectoryTableAddress = initialOffset
+ + (int)optionalHeader.DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(executable.SectionTable);
+ if (delayLoadDirectoryTableAddress >= data.Length)
+ return executable;
+
+ // Try to parse the delay-load directory table
+ int endOffset = (int)(delayLoadDirectoryTableAddress + optionalHeader.DelayImportDescriptor.Size);
+ var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data, delayLoadDirectoryTableAddress, endOffset);
+ if (delayLoadDirectoryTable == null)
+ return null;
+
+ // Set the delay-load directory table
+ executable.DelayLoadDirectoryTable = delayLoadDirectoryTable;
+ }
+
+ #endregion
#region Resource Directory Table
@@ -627,6 +647,37 @@ namespace BurnOutSharp.Builder
return attributeCertificateTable.ToArray();
}
+ ///
+ /// Parse a byte array into a delay-load directory table
+ ///
+ /// Byte array to parse
+ /// Offset into the byte array
+ /// First address not part of the delay-load directory table
+ /// Filled delay-load directory table on success, null on error
+ private static DelayLoadDirectoryTableEntry[] ParseDelayLoadDirectoryTable(byte[] data, int offset, int endOffset)
+ {
+ // TODO: Use marshalling here instead of building
+ var delayLoadDirectoryTable = new List();
+
+ while (offset < endOffset)
+ {
+ var entry = new DelayLoadDirectoryTableEntry();
+
+ entry.Attributes = data.ReadUInt32(ref offset);
+ entry.Name = data.ReadUInt32(ref offset);
+ entry.ModuleHandle = data.ReadUInt32(ref offset);
+ entry.DelayImportAddressTable = data.ReadUInt32(ref offset);
+ entry.DelayImportNameTable = data.ReadUInt32(ref offset);
+ entry.BoundDelayImportTable = data.ReadUInt32(ref offset);
+ entry.UnloadDelayImportTable = data.ReadUInt32(ref offset);
+ entry.TimeStamp = data.ReadUInt32(ref offset);
+
+ delayLoadDirectoryTable.Add(entry);
+ }
+
+ return delayLoadDirectoryTable.ToArray();
+ }
+
///
/// Parse a byte array into a resource directory table
///
@@ -907,7 +958,28 @@ namespace BurnOutSharp.Builder
#endregion
- // TODO: DelayLoadDirectoryTable
+ #region Delay-Load Directory Table
+
+ if (optionalHeader.DelayImportDescriptor != null && optionalHeader.DelayImportDescriptor.VirtualAddress != 0)
+ {
+ // If the offset for the delay-load directory table doesn't exist
+ int delayLoadDirectoryTableAddress = initialOffset
+ + (int)optionalHeader.DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(executable.SectionTable);
+ if (delayLoadDirectoryTableAddress >= data.Length)
+ return executable;
+
+ // Try to parse the delay-load directory table
+ data.Seek(delayLoadDirectoryTableAddress, SeekOrigin.Begin);
+ int endOffset = (int)(delayLoadDirectoryTableAddress + optionalHeader.DelayImportDescriptor.Size);
+ var delayLoadDirectoryTable = ParseDelayLoadDirectoryTable(data, endOffset);
+ if (delayLoadDirectoryTable == null)
+ return null;
+
+ // Set the delay-load directory table
+ executable.DelayLoadDirectoryTable = delayLoadDirectoryTable;
+ }
+
+ #endregion
#region Resource Directory Table
@@ -1377,6 +1449,36 @@ namespace BurnOutSharp.Builder
return attributeCertificateTable.ToArray();
}
+ ///
+ /// Parse a byte array into a delay-load directory table
+ ///
+ /// Stream to parse
+ /// First address not part of the delay-load directory table
+ /// Filled delay-load directory table on success, null on error
+ private static DelayLoadDirectoryTableEntry[] ParseDelayLoadDirectoryTable(Stream data, int endOffset)
+ {
+ // TODO: Use marshalling here instead of building
+ var delayLoadDirectoryTable = new List();
+
+ while (data.Position < endOffset)
+ {
+ var entry = new DelayLoadDirectoryTableEntry();
+
+ entry.Attributes = data.ReadUInt32();
+ entry.Name = data.ReadUInt32();
+ entry.ModuleHandle = data.ReadUInt32();
+ entry.DelayImportAddressTable = data.ReadUInt32();
+ entry.DelayImportNameTable = data.ReadUInt32();
+ entry.BoundDelayImportTable = data.ReadUInt32();
+ entry.UnloadDelayImportTable = data.ReadUInt32();
+ entry.TimeStamp = data.ReadUInt32();
+
+ delayLoadDirectoryTable.Add(entry);
+ }
+
+ return delayLoadDirectoryTable.ToArray();
+ }
+
///
/// Parse a Stream into a resource directory table
///