Copied remotely
[mono.git] / mcs / class / Mono.PEToolkit / CheckSum.cs
1
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.
21 //
22 /*\r
23  * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>\r
24  */\r
25 \r
26 // see http://cvs.winehq.com/cvsweb/wine/dlls/imagehlp/modify.c\r
27 // starting from Revision 1.8\r
28 \r
29 using System;\r
30 using System.IO;\r
31 \r
32 namespace Mono.PEToolkit {\r
33 \r
34         public sealed class CheckSum {\r
35 \r
36                 private CheckSum()\r
37                 {\r
38                         // Never instantiated.\r
39                 }\r
40 \r
41 \r
42                 public static uint Calc(string peFile)\r
43                 {\r
44                         uint res = 0;\r
45 \r
46                         FileInfo pe = new FileInfo(peFile);\r
47                         if (!pe.Exists) {\r
48                                 throw new Exception("CheckSum : Invalid file path.");\r
49                         }\r
50 \r
51                         using (BinaryReader reader = new BinaryReader(pe.OpenRead())) {\r
52                                 if (!reader.BaseStream.CanSeek) {\r
53                                         throw new Exception("Can't seek.");\r
54                                 }\r
55 \r
56                                 DOSHeader dosHdr = new DOSHeader();\r
57                                 COFFHeader coffHdr = new COFFHeader();\r
58                                 PEHeader peHdr = new PEHeader();\r
59 \r
60                                 dosHdr.Read (reader);\r
61                                 reader.BaseStream.Position = dosHdr.Lfanew;\r
62                                 ExeSignature peSig = (ExeSignature) reader.ReadUInt16();\r
63                                 if (peSig != ExeSignature.NT) {\r
64                                         throw new BadImageException("Checksum : Invalid image format, cannot find PE signature.");\r
65                                 }\r
66         \r
67                                 peSig = (ExeSignature) reader.ReadUInt16();\r
68                                 if (peSig != ExeSignature.NT2) {\r
69                                         throw new BadImageException("Checksum : Invalid image format, cannot find PE signature.");\r
70                                 }\r
71 \r
72                                 coffHdr.Read(reader);\r
73                                 peHdr.Read(reader);\r
74 \r
75                                 uint oldSum = peHdr.CheckSum;\r
76                                 reader.BaseStream.Position = 0;\r
77                                 long len = pe.Length;\r
78                                 long whole = len >> 1;\r
79                                 uint sum = 0;\r
80                                 uint hi, lo;\r
81                                 for (long i = whole; --i >= 0;) {\r
82                                         sum += reader.ReadUInt16();\r
83                                         hi = sum >> 16;\r
84                                         if (hi != 0) {\r
85                                                 sum = hi + (sum & 0xFFFF);\r
86                                         }\r
87                                 }\r
88                                 if ((len & 1L) != 0) {\r
89                                         sum += (uint) reader.ReadByte();\r
90                                         hi = sum >> 16;\r
91                                         if (hi != 0) {\r
92                                                 sum = hi + (sum & 0xFFFF);\r
93                                         }\r
94                                 }\r
95 \r
96                                 // fix low word of checksum\r
97                                 lo = oldSum & 0xFFFF;\r
98                                 if ((sum & 0xFFFF) >= lo) {\r
99                                         sum -= lo;\r
100                                 } else {\r
101                                         sum = (((sum & 0xFFFF) - lo) & 0xFFFF) - 1;\r
102                                 }\r
103 \r
104                                 // fix high word of checksum\r
105                                 hi = oldSum >> 16;\r
106                                 if ((sum & 0xFFFF) >= hi) {\r
107                                         sum -= hi;\r
108                                 } else {\r
109                                         sum = (((sum & 0xFFFF) - hi) & 0xFFFF) - 1;\r
110                                 }\r
111                         }\r
112 \r
113                         return res;\r
114                 }\r
115         }\r
116 \r
117 }\r