/* * Copyright (c) 2002 Sergey Chaban */ // see http://cvs.winehq.com/cvsweb/wine/dlls/imagehlp/modify.c // starting from Revision 1.8 using System; using System.IO; namespace Mono.PEToolkit { public sealed class CheckSum { private CheckSum() { // Never instantiated. } public static uint Calc(string peFile) { uint res = 0; FileInfo pe = new FileInfo(peFile); if (!pe.Exists) { throw new Exception("CheckSum : Invalid file path."); } using (BinaryReader reader = new BinaryReader(pe.OpenRead())) { if (!reader.BaseStream.CanSeek) { throw new Exception("Can't seek."); } DOSHeader dosHdr = new DOSHeader(); COFFHeader coffHdr = new COFFHeader(); PEHeader peHdr = new PEHeader(); dosHdr.Read (reader); reader.BaseStream.Position = dosHdr.lfanew; ExeSignature peSig = (ExeSignature) reader.ReadUInt16(); if (peSig != ExeSignature.NT) { throw new BadImageException("Checksum : Invalid image format, cannot find PE signature."); } peSig = (ExeSignature) reader.ReadUInt16(); if (peSig != ExeSignature.NT2) { throw new BadImageException("Checksum : Invalid image format, cannot find PE signature."); } coffHdr.Read(reader); peHdr.Read(reader); uint oldSum = peHdr.CheckSum; reader.BaseStream.Position = 0; long len = pe.Length; long whole = len >> 1; uint sum = 0; uint hi, lo; for (long i = whole; --i >= 0;) { sum += reader.ReadUInt16(); hi = sum >> 16; if (hi != 0) { sum = hi + (sum & 0xFFFF); } } if ((len & 1L) != 0) { sum += (uint) reader.ReadByte(); hi = sum >> 16; if (hi != 0) { sum = hi + (sum & 0xFFFF); } } // fix low word of checksum lo = oldSum & 0xFFFF; if ((sum & 0xFFFF) >= lo) { sum -= lo; } else { sum = (((sum & 0xFFFF) - lo) & 0xFFFF) - 1; } // fix high word of checksum hi = oldSum >> 16; if ((sum & 0xFFFF) >= hi) { sum -= hi; } else { sum = (((sum & 0xFFFF) - hi) & 0xFFFF) - 1; } } return res; } } }