Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

398 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. checksum.c
  5. Abstract:
  6. This module implements a function for computing the checksum of an
  7. image file. It will also compute the checksum of other files as well.
  8. Author:
  9. David N. Cutler (davec) 21-Mar-1993
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <private.h>
  16. //
  17. // Define checksum routine prototype.
  18. //
  19. #ifdef __cplusplus
  20. extern "C"
  21. #endif
  22. USHORT
  23. ChkSum(
  24. DWORD PartialSum,
  25. PUSHORT Source,
  26. DWORD Length
  27. );
  28. PIMAGE_NT_HEADERS
  29. CheckSumMappedFile (
  30. LPVOID BaseAddress,
  31. DWORD FileLength,
  32. LPDWORD HeaderSum,
  33. LPDWORD CheckSum
  34. )
  35. /*++
  36. Routine Description:
  37. This functions computes the checksum of a mapped file.
  38. Arguments:
  39. BaseAddress - Supplies a pointer to the base of the mapped file.
  40. FileLength - Supplies the length of the file in bytes.
  41. HeaderSum - Suppllies a pointer to a variable that receives the checksum
  42. from the image file, or zero if the file is not an image file.
  43. CheckSum - Supplies a pointer to the variable that receive the computed
  44. checksum.
  45. Return Value:
  46. None.
  47. --*/
  48. {
  49. PUSHORT AdjustSum;
  50. PIMAGE_NT_HEADERS NtHeaders;
  51. USHORT PartialSum;
  52. PBYTE pbyte;
  53. //
  54. // Compute the checksum of the file and zero the header checksum value.
  55. //
  56. *HeaderSum = 0;
  57. PartialSum = ChkSum(0, (PUSHORT)BaseAddress, FileLength >> 1);
  58. //
  59. // If the file is an image file, then subtract the two checksum words
  60. // in the optional header from the computed checksum before adding
  61. // the file length, and set the value of the header checksum.
  62. //
  63. __try {
  64. NtHeaders = RtlpImageNtHeader(BaseAddress);
  65. } __except(EXCEPTION_EXECUTE_HANDLER) {
  66. NtHeaders = NULL;
  67. }
  68. if ((NtHeaders != NULL) && (NtHeaders != BaseAddress)) {
  69. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  70. *HeaderSum = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum;
  71. AdjustSum = (PUSHORT)(&((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum);
  72. } else
  73. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  74. *HeaderSum = ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum;
  75. AdjustSum = (PUSHORT)(&((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum);
  76. } else {
  77. return(NULL);
  78. }
  79. PartialSum -= (PartialSum < AdjustSum[0]);
  80. PartialSum -= AdjustSum[0];
  81. PartialSum -= (PartialSum < AdjustSum[1]);
  82. PartialSum -= AdjustSum[1];
  83. }
  84. // add the last byte, if needed
  85. if (FileLength % 2) {
  86. pbyte = (PBYTE)BaseAddress + FileLength - 1;
  87. PartialSum += *pbyte;
  88. PartialSum = (PartialSum >> 16) + (PartialSum & 0xFFFF);
  89. }
  90. //
  91. // Compute the final checksum value as the sum of the paritial checksum
  92. // and the file length.
  93. //
  94. *CheckSum = (DWORD)PartialSum + FileLength;
  95. return NtHeaders;
  96. }
  97. DWORD
  98. MapFileAndCheckSumW(
  99. PWSTR Filename,
  100. LPDWORD HeaderSum,
  101. LPDWORD CheckSum
  102. )
  103. /*++
  104. Routine Description:
  105. This functions maps the specified file and computes the checksum of
  106. the file.
  107. Arguments:
  108. Filename - Supplies a pointer to the name of the file whose checksum
  109. is computed.
  110. HeaderSum - Supplies a pointer to a variable that receives the checksum
  111. from the image file, or zero if the file is not an image file.
  112. CheckSum - Supplies a pointer to the variable that receive the computed
  113. checksum.
  114. Return Value:
  115. 0 if successful, else error number.
  116. --*/
  117. {
  118. #ifndef UNICODE_RULES
  119. CHAR FileNameA[ MAX_PATH ];
  120. // Convert the file name to Ansi and call the Ansi version
  121. // of this function.
  122. if (WideCharToMultiByte(
  123. CP_ACP,
  124. 0,
  125. Filename,
  126. -1,
  127. FileNameA,
  128. MAX_PATH,
  129. NULL,
  130. NULL ) ) {
  131. return MapFileAndCheckSumA(FileNameA, HeaderSum, CheckSum);
  132. }
  133. return CHECKSUM_UNICODE_FAILURE;
  134. #else // UNICODE_RULES
  135. HANDLE FileHandle, MappingHandle;
  136. LPVOID BaseAddress;
  137. DWORD FileLength;
  138. //
  139. // Open the file for read access
  140. //
  141. FileHandle = CreateFileW(
  142. Filename,
  143. GENERIC_READ,
  144. FILE_SHARE_READ | FILE_SHARE_WRITE,
  145. NULL,
  146. OPEN_EXISTING,
  147. FILE_ATTRIBUTE_NORMAL,
  148. NULL );
  149. if (FileHandle == INVALID_HANDLE_VALUE) {
  150. return CHECKSUM_OPEN_FAILURE;
  151. }
  152. //
  153. // Create a file mapping, map a view of the file into memory,
  154. // and close the file mapping handle.
  155. //
  156. MappingHandle = CreateFileMapping(FileHandle,
  157. NULL,
  158. PAGE_READONLY,
  159. 0,
  160. 0,
  161. NULL);
  162. if (!MappingHandle) {
  163. CloseHandle( FileHandle );
  164. return CHECKSUM_MAP_FAILURE;
  165. }
  166. //
  167. // Map a view of the file
  168. //
  169. BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_READ, 0, 0, 0);
  170. CloseHandle(MappingHandle);
  171. if (BaseAddress == NULL) {
  172. CloseHandle( FileHandle );
  173. return CHECKSUM_MAPVIEW_FAILURE;
  174. }
  175. //
  176. // Get the length of the file in bytes and compute the checksum.
  177. //
  178. FileLength = GetFileSize( FileHandle, NULL );
  179. CheckSumMappedFile(BaseAddress, FileLength, HeaderSum, CheckSum);
  180. //
  181. // Unmap the view of the file and close file handle.
  182. //
  183. UnmapViewOfFile(BaseAddress);
  184. CloseHandle( FileHandle );
  185. return CHECKSUM_SUCCESS;
  186. #endif // UNICODE_RULES
  187. }
  188. ULONG
  189. MapFileAndCheckSumA (
  190. LPSTR Filename,
  191. LPDWORD HeaderSum,
  192. LPDWORD CheckSum
  193. )
  194. /*++
  195. Routine Description:
  196. This functions maps the specified file and computes the checksum of
  197. the file.
  198. Arguments:
  199. Filename - Supplies a pointer to the name of the file whose checksum
  200. is computed.
  201. HeaderSum - Supplies a pointer to a variable that receives the checksum
  202. from the image file, or zero if the file is not an image file.
  203. CheckSum - Supplies a pointer to the variable that receive the computed
  204. checksum.
  205. Return Value:
  206. 0 if successful, else error number.
  207. --*/
  208. {
  209. #ifdef UNICODE_RULES
  210. WCHAR FileNameW[ MAX_PATH ];
  211. //
  212. // Convert the file name to unicode and call the unicode version
  213. // of this function.
  214. //
  215. if (MultiByteToWideChar(
  216. CP_ACP,
  217. MB_PRECOMPOSED,
  218. Filename,
  219. -1,
  220. FileNameW,
  221. MAX_PATH ) ) {
  222. return MapFileAndCheckSumW(FileNameW, HeaderSum, CheckSum);
  223. }
  224. return CHECKSUM_UNICODE_FAILURE;
  225. #else // UNICODE_RULES
  226. HANDLE FileHandle, MappingHandle;
  227. LPVOID BaseAddress;
  228. DWORD FileLength;
  229. //
  230. // Open the file for read access
  231. //
  232. FileHandle = CreateFileA(
  233. Filename,
  234. GENERIC_READ,
  235. FILE_SHARE_READ | FILE_SHARE_WRITE,
  236. NULL,
  237. OPEN_EXISTING,
  238. FILE_ATTRIBUTE_NORMAL,
  239. NULL );
  240. if (FileHandle == INVALID_HANDLE_VALUE) {
  241. return CHECKSUM_OPEN_FAILURE;
  242. }
  243. //
  244. // Create a file mapping, map a view of the file into memory,
  245. // and close the file mapping handle.
  246. //
  247. MappingHandle = CreateFileMapping(FileHandle,
  248. NULL,
  249. PAGE_READONLY,
  250. 0,
  251. 0,
  252. NULL);
  253. if (!MappingHandle) {
  254. CloseHandle( FileHandle );
  255. return CHECKSUM_MAP_FAILURE;
  256. }
  257. //
  258. // Map a view of the file
  259. //
  260. BaseAddress = MapViewOfFile(MappingHandle, FILE_MAP_READ, 0, 0, 0);
  261. CloseHandle(MappingHandle);
  262. if (BaseAddress == NULL) {
  263. CloseHandle( FileHandle );
  264. return CHECKSUM_MAPVIEW_FAILURE;
  265. }
  266. //
  267. // Get the length of the file in bytes and compute the checksum.
  268. //
  269. FileLength = GetFileSize( FileHandle, NULL );
  270. CheckSumMappedFile(BaseAddress, FileLength, HeaderSum, CheckSum);
  271. //
  272. // Unmap the view of the file and close file handle.
  273. //
  274. UnmapViewOfFile(BaseAddress);
  275. CloseHandle( FileHandle );
  276. return CHECKSUM_SUCCESS;
  277. #endif // UNICODE_RULES
  278. }
  279. BOOL
  280. TouchFileTimes(
  281. HANDLE FileHandle,
  282. LPSYSTEMTIME lpSystemTime
  283. )
  284. {
  285. SYSTEMTIME SystemTime;
  286. FILETIME SystemFileTime;
  287. if (lpSystemTime == NULL) {
  288. lpSystemTime = &SystemTime;
  289. GetSystemTime( lpSystemTime );
  290. }
  291. if (SystemTimeToFileTime( lpSystemTime, &SystemFileTime )) {
  292. return SetFileTime( FileHandle, NULL, NULL, &SystemFileTime );
  293. }
  294. else {
  295. return FALSE;
  296. }
  297. }