// dnlib: See LICENSE.txt for more info
using System;
using System.IO;
namespace dnlib.PE {
///
/// Extension methods
///
public static partial class PEExtensions {
///
/// Calculates a PE checksum
///
/// PE image stream positioned at the MZ bytes
/// Length of image
/// Offset of checksum
/// PE checksum
internal static uint CalculatePECheckSum(this Stream stream, long length, long checkSumOffset) {
if ((length & 1) != 0)
ThrowInvalidOperationException("Invalid PE length");
var buffer = new byte[(int)Math.Min(length, 0x2000)];
uint checkSum = 0;
checkSum = CalculatePECheckSum(stream, checkSumOffset, checkSum, buffer);
const int ChecksumFieldSize = 4;
stream.Position += ChecksumFieldSize;
checkSum = CalculatePECheckSum(stream, length - checkSumOffset - ChecksumFieldSize, checkSum, buffer);
ulong cks = (ulong)checkSum + (ulong)length;
return (uint)cks + (uint)(cks >> 32);
}
static uint CalculatePECheckSum(Stream stream, long length, uint checkSum, byte[] buffer) {
for (long offset = 0; offset < length;) {
int len = (int)Math.Min(length - offset, buffer.Length);
int count = stream.Read(buffer, 0, len);
if (count != len)
ThrowInvalidOperationException("Couldn't read all bytes");
for (int i = 0; i < count;) {
checkSum += buffer[i++] | ((uint)buffer[i++] << 8);
checkSum = (ushort)(checkSum + (checkSum >> 16));
}
offset += count;
}
return checkSum;
}
static void ThrowInvalidOperationException(string message) => throw new InvalidOperationException(message);
}
}