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