2007-03-28 Chris Toshok <toshok@ximian.com>
[mono-project.git] / mcs / class / Mono.PEToolkit / CheckSum.cs
blobb842eaa63f1706bbc69723a254cf375b0bc02166
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
26 // see http://cvs.winehq.com/cvsweb/wine/dlls/imagehlp/modify.c
27 // starting from Revision 1.8
29 using System;
30 using System.IO;
32 namespace Mono.PEToolkit {
34 public sealed class CheckSum {
36 private CheckSum()
38 // Never instantiated.
42 public static uint Calc(string peFile)
44 uint res = 0;
46 FileInfo pe = new FileInfo(peFile);
47 if (!pe.Exists) {
48 throw new Exception("CheckSum : Invalid file path.");
51 using (BinaryReader reader = new BinaryReader(pe.OpenRead())) {
52 if (!reader.BaseStream.CanSeek) {
53 throw new Exception("Can't seek.");
56 DOSHeader dosHdr = new DOSHeader();
57 COFFHeader coffHdr = new COFFHeader();
58 PEHeader peHdr = new PEHeader();
60 dosHdr.Read (reader);
61 reader.BaseStream.Position = dosHdr.Lfanew;
62 ExeSignature peSig = (ExeSignature) reader.ReadUInt16();
63 if (peSig != ExeSignature.NT) {
64 throw new BadImageException("Checksum : Invalid image format, cannot find PE signature.");
67 peSig = (ExeSignature) reader.ReadUInt16();
68 if (peSig != ExeSignature.NT2) {
69 throw new BadImageException("Checksum : Invalid image format, cannot find PE signature.");
72 coffHdr.Read(reader);
73 peHdr.Read(reader);
75 uint oldSum = peHdr.CheckSum;
76 reader.BaseStream.Position = 0;
77 long len = pe.Length;
78 long whole = len >> 1;
79 uint sum = 0;
80 uint hi, lo;
81 for (long i = whole; --i >= 0;) {
82 sum += reader.ReadUInt16();
83 hi = sum >> 16;
84 if (hi != 0) {
85 sum = hi + (sum & 0xFFFF);
88 if ((len & 1L) != 0) {
89 sum += (uint) reader.ReadByte();
90 hi = sum >> 16;
91 if (hi != 0) {
92 sum = hi + (sum & 0xFFFF);
96 // fix low word of checksum
97 lo = oldSum & 0xFFFF;
98 if ((sum & 0xFFFF) >= lo) {
99 sum -= lo;
100 } else {
101 sum = (((sum & 0xFFFF) - lo) & 0xFFFF) - 1;
104 // fix high word of checksum
105 hi = oldSum >> 16;
106 if ((sum & 0xFFFF) >= hi) {
107 sum -= hi;
108 } else {
109 sum = (((sum & 0xFFFF) - hi) & 0xFFFF) - 1;
113 return res;