Leaked source code of windows server 2003
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.

402 lines
9.4 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 21-Mar-1993
  10. Revision History:
  11. --*/
  12. #include <windows.h>
  13. #include "checksum.h"
  14. #include "rlmsgtbl.h"
  15. void QuitA( int, LPSTR, LPSTR);
  16. void QuitW( int, LPWSTR, LPWSTR);
  17. // Helper routines
  18. static PIMAGE_NT_HEADERS ImageNtHeader( PVOID Base);
  19. static USHORT ChkSum( DWORD PartialSum,
  20. PUSHORT Source,
  21. DWORD Length);
  22. static PIMAGE_NT_HEADERS
  23. CheckSumMappedFile (
  24. LPVOID pBaseAddress,
  25. DWORD dwFileLength,
  26. LPDWORD pdwHeaderSum,
  27. LPDWORD pdwCheckSum
  28. );
  29. static BOOL
  30. TouchFileTimes (
  31. HANDLE hFileHandle,
  32. LPSYSTEMTIME lpSystemTime
  33. );
  34. /*++
  35. Routine Description:
  36. This function returns the address of the NT Header.
  37. Arguments:
  38. Base - Supplies the base of the image.
  39. Return Value:
  40. Returns the address of the NT Header.
  41. --*/
  42. static PIMAGE_NT_HEADERS ImageNtHeader( PVOID pBase)
  43. {
  44. PIMAGE_NT_HEADERS pNtHeaders = NULL;
  45. if ( pBase != NULL && pBase != (PVOID)-1 )
  46. {
  47. if ( ((PIMAGE_DOS_HEADER)pBase)->e_magic == IMAGE_DOS_SIGNATURE )
  48. {
  49. pNtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)pBase + ((PIMAGE_DOS_HEADER)pBase)->e_lfanew);
  50. if ( pNtHeaders->Signature != IMAGE_NT_SIGNATURE )
  51. {
  52. pNtHeaders = NULL;
  53. }
  54. }
  55. }
  56. return( pNtHeaders);
  57. }
  58. /*++
  59. Routine Description:
  60. Compute a partial checksum on a portion of an imagefile.
  61. Arguments:
  62. PartialSum - Supplies the initial checksum value.
  63. Sources - Supplies a pointer to the array of words for which the
  64. checksum is computed.
  65. Length - Supplies the length of the array in words.
  66. Return Value:
  67. The computed checksum value is returned as the function value.
  68. --*/
  69. static USHORT ChkSum(
  70. ULONG PartialSum,
  71. PUSHORT Source,
  72. ULONG Length)
  73. {
  74. //
  75. // Compute the word wise checksum allowing carries to occur into the
  76. // high order half of the checksum longword.
  77. //
  78. while (Length--) {
  79. PartialSum += *Source++;
  80. PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff);
  81. }
  82. //
  83. // Fold final carry into a single word result and return the resultant
  84. // value.
  85. //
  86. return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff);
  87. }
  88. /*++
  89. Routine Description:
  90. This functions computes the checksum of a mapped file.
  91. Arguments:
  92. BaseAddress - Supplies a pointer to the base of the mapped file.
  93. FileLength - Supplies the length of the file in bytes.
  94. HeaderSum - Suppllies a pointer to a variable that receives the checksum
  95. from the image file, or zero if the file is not an image file.
  96. CheckSum - Supplies a pointer to the variable that receive the computed
  97. checksum.
  98. Return Value:
  99. None.
  100. --*/
  101. static PIMAGE_NT_HEADERS CheckSumMappedFile(
  102. LPVOID pBaseAddress,
  103. DWORD dwFileLength,
  104. LPDWORD pdwHeaderSum,
  105. LPDWORD pdwCheckSum)
  106. {
  107. USHORT usPartialSum;
  108. PUSHORT pusAdjustSum;
  109. PIMAGE_NT_HEADERS pNtHeaders = NULL;
  110. //
  111. // Compute the checksum of the file and zero the header checksum value.
  112. //
  113. *pdwHeaderSum = 0;
  114. usPartialSum = ChkSum(0, (PUSHORT)pBaseAddress, (dwFileLength + 1) >> 1);
  115. //
  116. // If the file is an image file, then subtract the two checksum words
  117. // in the optional header from the computed checksum before adding
  118. // the file length, and set the value of the header checksum.
  119. //
  120. pNtHeaders = ImageNtHeader( pBaseAddress);
  121. if ( (pNtHeaders != NULL) && (pNtHeaders != pBaseAddress) )
  122. {
  123. *pdwHeaderSum = pNtHeaders->OptionalHeader.CheckSum;
  124. pusAdjustSum = (PUSHORT)(&pNtHeaders->OptionalHeader.CheckSum);
  125. usPartialSum -= (usPartialSum < pusAdjustSum[0]);
  126. usPartialSum -= pusAdjustSum[0];
  127. usPartialSum -= (usPartialSum < pusAdjustSum[1]);
  128. usPartialSum -= pusAdjustSum[1];
  129. }
  130. //
  131. // Compute the final checksum value as the sum of the paritial checksum
  132. // and the file length.
  133. //
  134. *pdwCheckSum = (DWORD)usPartialSum + dwFileLength;
  135. return( pNtHeaders);
  136. }
  137. /*++
  138. Routine Description:
  139. This functions maps the specified file and computes the checksum of
  140. the file.
  141. Arguments:
  142. Filename - Supplies a pointer to the name of the file whose checksum
  143. is computed.
  144. HeaderSum - Supplies a pointer to a variable that receives the checksum
  145. from the image file, or zero if the file is not an image file.
  146. CheckSum - Supplies a pointer to the variable that receive the computed
  147. checksum.
  148. Return Value:
  149. 0 if successful, else error number.
  150. --*/
  151. DWORD MapFileAndFixCheckSumW( PWSTR pszwFilename)
  152. {
  153. HANDLE hFileHandle = NULL;
  154. HANDLE hMappingHandle = NULL;
  155. LPVOID pBaseAddress = NULL;
  156. DWORD dwFileLength = 0;
  157. DWORD dwHeaderSum = 0;
  158. DWORD dwCheckSum = 0;
  159. DWORD dwOldCheckSum = 0;
  160. PIMAGE_NT_HEADERS pNtHeaders = NULL;
  161. //
  162. // Open the file for read access
  163. //
  164. hFileHandle = CreateFileW( pszwFilename,
  165. GENERIC_READ | GENERIC_WRITE,
  166. FILE_SHARE_READ | FILE_SHARE_WRITE,
  167. NULL,
  168. OPEN_EXISTING,
  169. FILE_ATTRIBUTE_NORMAL,
  170. NULL);
  171. if ( hFileHandle == INVALID_HANDLE_VALUE )
  172. {
  173. QuitW( IDS_ENGERR_01, L"image", pszwFilename);
  174. }
  175. //
  176. // Create a file mapping, map a view of the file into memory,
  177. // and close the file mapping handle.
  178. //
  179. hMappingHandle = CreateFileMapping( hFileHandle,
  180. NULL,
  181. PAGE_READWRITE,
  182. 0,
  183. 0,
  184. NULL);
  185. if ( hMappingHandle == NULL )
  186. {
  187. CloseHandle( hFileHandle );
  188. QuitW( IDS_ENGERR_22, pszwFilename, NULL);
  189. }
  190. //
  191. // Map a view of the file
  192. //
  193. pBaseAddress = MapViewOfFile( hMappingHandle,
  194. FILE_MAP_READ | FILE_MAP_WRITE,
  195. 0,
  196. 0,
  197. 0);
  198. CloseHandle( hMappingHandle);
  199. if ( pBaseAddress == NULL )
  200. {
  201. CloseHandle( hFileHandle );
  202. QuitW( IDS_ENGERR_23, pszwFilename, NULL);
  203. }
  204. //
  205. // Get the length of the file in bytes and compute the checksum.
  206. //
  207. dwFileLength = GetFileSize( hFileHandle, NULL );
  208. pNtHeaders = CheckSumMappedFile( pBaseAddress, dwFileLength, &dwHeaderSum, &dwCheckSum);
  209. if ( pNtHeaders == NULL )
  210. {
  211. CloseHandle( hFileHandle );
  212. UnmapViewOfFile( pBaseAddress );
  213. QuitW( IDS_ENGERR_17, pszwFilename, NULL);
  214. }
  215. dwOldCheckSum = pNtHeaders->OptionalHeader.CheckSum;
  216. pNtHeaders->OptionalHeader.CheckSum = dwCheckSum;
  217. if ( ! FlushViewOfFile( pBaseAddress, dwFileLength) )
  218. {
  219. UnmapViewOfFile( pBaseAddress);
  220. CloseHandle( hFileHandle);
  221. QuitW( IDS_ENGERR_24, pszwFilename, NULL);
  222. }
  223. UnmapViewOfFile( pBaseAddress);
  224. if ( dwCheckSum != dwOldCheckSum )
  225. {
  226. if ( ! TouchFileTimes( hFileHandle, NULL) )
  227. {
  228. CloseHandle( hFileHandle);
  229. QuitW( IDS_ENGERR_25, pszwFilename, NULL);
  230. }
  231. }
  232. CloseHandle( hFileHandle);
  233. return( 0);
  234. }
  235. /*++
  236. Routine Description:
  237. This functions maps the specified file and computes the checksum of
  238. the file.
  239. Arguments:
  240. Filename - Supplies a pointer to the name of the file whose checksum
  241. is computed.
  242. HeaderSum - Supplies a pointer to a variable that receives the checksum
  243. from the image file, or zero if the file is not an image file.
  244. CheckSum - Supplies a pointer to the variable that receive the computed
  245. checksum.
  246. Return Value:
  247. 0 if successful, else error number.
  248. --*/
  249. ULONG MapFileAndFixCheckSumA( LPSTR pszFilename)
  250. {
  251. WCHAR szFileNameW[ MAX_PATH ];
  252. //
  253. // Convert the file name to unicode and call the unicode version
  254. // of this function.
  255. //
  256. if ( MultiByteToWideChar( CP_ACP,
  257. MB_PRECOMPOSED,
  258. pszFilename,
  259. -1,
  260. szFileNameW,
  261. MAX_PATH) )
  262. {
  263. return( MapFileAndFixCheckSumW( szFileNameW));
  264. }
  265. return( (ULONG)-1L);
  266. }
  267. //.........................................
  268. static BOOL TouchFileTimes(
  269. HANDLE FileHandle,
  270. LPSYSTEMTIME lpSystemTime)
  271. {
  272. SYSTEMTIME SystemTime;
  273. FILETIME SystemFileTime;
  274. if ( lpSystemTime == NULL )
  275. {
  276. lpSystemTime = &SystemTime;
  277. GetSystemTime( lpSystemTime );
  278. }
  279. if ( SystemTimeToFileTime( lpSystemTime, &SystemFileTime ) )
  280. {
  281. return( SetFileTime( FileHandle, NULL, NULL, &SystemFileTime ));
  282. }
  283. else
  284. {
  285. return( FALSE);
  286. }
  287. }