|
|
/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
checksum.c
Abstract:
This module implements a function for computing the checksum of an image file. It will also compute the checksum of other files as well.
Author:
David N. Cutler 21-Mar-1993
Revision History:
--*/
#include <windows.h>
#include "checksum.h"
#include "rlmsgtbl.h"
void QuitA( int, LPSTR, LPSTR); void QuitW( int, LPWSTR, LPWSTR);
// Helper routines
static PIMAGE_NT_HEADERS ImageNtHeader( PVOID Base); static USHORT ChkSum( DWORD PartialSum, PUSHORT Source, DWORD Length);
static PIMAGE_NT_HEADERS CheckSumMappedFile ( LPVOID pBaseAddress, DWORD dwFileLength, LPDWORD pdwHeaderSum, LPDWORD pdwCheckSum );
static BOOL TouchFileTimes ( HANDLE hFileHandle, LPSYSTEMTIME lpSystemTime );
/*++
Routine Description:
This function returns the address of the NT Header.
Arguments:
Base - Supplies the base of the image.
Return Value:
Returns the address of the NT Header.
--*/
static PIMAGE_NT_HEADERS ImageNtHeader( PVOID pBase) { PIMAGE_NT_HEADERS pNtHeaders = NULL;
if ( pBase != NULL && pBase != (PVOID)-1 ) { if ( ((PIMAGE_DOS_HEADER)pBase)->e_magic == IMAGE_DOS_SIGNATURE ) { pNtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)pBase + ((PIMAGE_DOS_HEADER)pBase)->e_lfanew);
if ( pNtHeaders->Signature != IMAGE_NT_SIGNATURE ) { pNtHeaders = NULL; } } } return( pNtHeaders); }
/*++
Routine Description:
Compute a partial checksum on a portion of an imagefile.
Arguments:
PartialSum - Supplies the initial checksum value.
Sources - Supplies a pointer to the array of words for which the checksum is computed.
Length - Supplies the length of the array in words.
Return Value:
The computed checksum value is returned as the function value.
--*/
static USHORT ChkSum(
ULONG PartialSum, PUSHORT Source, ULONG Length) {
//
// Compute the word wise checksum allowing carries to occur into the
// high order half of the checksum longword.
//
while (Length--) { PartialSum += *Source++; PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff); }
//
// Fold final carry into a single word result and return the resultant
// value.
//
return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff); }
/*++
Routine Description:
This functions computes the checksum of a mapped file.
Arguments:
BaseAddress - Supplies a pointer to the base of the mapped file.
FileLength - Supplies the length of the file in bytes.
HeaderSum - Suppllies a pointer to a variable that receives the checksum from the image file, or zero if the file is not an image file.
CheckSum - Supplies a pointer to the variable that receive the computed checksum.
Return Value:
None.
--*/
static PIMAGE_NT_HEADERS CheckSumMappedFile(
LPVOID pBaseAddress, DWORD dwFileLength, LPDWORD pdwHeaderSum, LPDWORD pdwCheckSum) { USHORT usPartialSum; PUSHORT pusAdjustSum; PIMAGE_NT_HEADERS pNtHeaders = NULL;
//
// Compute the checksum of the file and zero the header checksum value.
//
*pdwHeaderSum = 0; usPartialSum = ChkSum(0, (PUSHORT)pBaseAddress, (dwFileLength + 1) >> 1);
//
// If the file is an image file, then subtract the two checksum words
// in the optional header from the computed checksum before adding
// the file length, and set the value of the header checksum.
//
pNtHeaders = ImageNtHeader( pBaseAddress);
if ( (pNtHeaders != NULL) && (pNtHeaders != pBaseAddress) ) { *pdwHeaderSum = pNtHeaders->OptionalHeader.CheckSum; pusAdjustSum = (PUSHORT)(&pNtHeaders->OptionalHeader.CheckSum); usPartialSum -= (usPartialSum < pusAdjustSum[0]); usPartialSum -= pusAdjustSum[0]; usPartialSum -= (usPartialSum < pusAdjustSum[1]); usPartialSum -= pusAdjustSum[1]; }
//
// Compute the final checksum value as the sum of the paritial checksum
// and the file length.
//
*pdwCheckSum = (DWORD)usPartialSum + dwFileLength; return( pNtHeaders); }
/*++
Routine Description:
This functions maps the specified file and computes the checksum of the file.
Arguments:
Filename - Supplies a pointer to the name of the file whose checksum is computed.
HeaderSum - Supplies a pointer to a variable that receives the checksum from the image file, or zero if the file is not an image file.
CheckSum - Supplies a pointer to the variable that receive the computed checksum.
Return Value:
0 if successful, else error number.
--*/
DWORD MapFileAndFixCheckSumW( PWSTR pszwFilename) { HANDLE hFileHandle = NULL; HANDLE hMappingHandle = NULL; LPVOID pBaseAddress = NULL; DWORD dwFileLength = 0; DWORD dwHeaderSum = 0; DWORD dwCheckSum = 0; DWORD dwOldCheckSum = 0; PIMAGE_NT_HEADERS pNtHeaders = NULL;
//
// Open the file for read access
//
hFileHandle = CreateFileW( pszwFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ( hFileHandle == INVALID_HANDLE_VALUE ) { QuitW( IDS_ENGERR_01, L"image", pszwFilename); }
//
// Create a file mapping, map a view of the file into memory,
// and close the file mapping handle.
//
hMappingHandle = CreateFileMapping( hFileHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
if ( hMappingHandle == NULL ) { CloseHandle( hFileHandle ); QuitW( IDS_ENGERR_22, pszwFilename, NULL); }
//
// Map a view of the file
//
pBaseAddress = MapViewOfFile( hMappingHandle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); CloseHandle( hMappingHandle);
if ( pBaseAddress == NULL ) { CloseHandle( hFileHandle ); QuitW( IDS_ENGERR_23, pszwFilename, NULL); }
//
// Get the length of the file in bytes and compute the checksum.
//
dwFileLength = GetFileSize( hFileHandle, NULL ); pNtHeaders = CheckSumMappedFile( pBaseAddress, dwFileLength, &dwHeaderSum, &dwCheckSum);
if ( pNtHeaders == NULL ) { CloseHandle( hFileHandle ); UnmapViewOfFile( pBaseAddress ); QuitW( IDS_ENGERR_17, pszwFilename, NULL); }
dwOldCheckSum = pNtHeaders->OptionalHeader.CheckSum;
pNtHeaders->OptionalHeader.CheckSum = dwCheckSum; if ( ! FlushViewOfFile( pBaseAddress, dwFileLength) ) { UnmapViewOfFile( pBaseAddress); CloseHandle( hFileHandle); QuitW( IDS_ENGERR_24, pszwFilename, NULL); } UnmapViewOfFile( pBaseAddress);
if ( dwCheckSum != dwOldCheckSum ) { if ( ! TouchFileTimes( hFileHandle, NULL) ) { CloseHandle( hFileHandle); QuitW( IDS_ENGERR_25, pszwFilename, NULL); } }
CloseHandle( hFileHandle); return( 0); }
/*++
Routine Description:
This functions maps the specified file and computes the checksum of the file.
Arguments:
Filename - Supplies a pointer to the name of the file whose checksum is computed.
HeaderSum - Supplies a pointer to a variable that receives the checksum from the image file, or zero if the file is not an image file.
CheckSum - Supplies a pointer to the variable that receive the computed checksum.
Return Value:
0 if successful, else error number.
--*/
ULONG MapFileAndFixCheckSumA( LPSTR pszFilename) { WCHAR szFileNameW[ MAX_PATH ];
//
// Convert the file name to unicode and call the unicode version
// of this function.
//
if ( MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszFilename, -1, szFileNameW, MAX_PATH) ) { return( MapFileAndFixCheckSumW( szFileNameW)); } return( (ULONG)-1L); }
//.........................................
static BOOL TouchFileTimes(
HANDLE FileHandle, LPSYSTEMTIME lpSystemTime) { SYSTEMTIME SystemTime; FILETIME SystemFileTime;
if ( lpSystemTime == NULL ) { lpSystemTime = &SystemTime; GetSystemTime( lpSystemTime ); }
if ( SystemTimeToFileTime( lpSystemTime, &SystemFileTime ) ) { return( SetFileTime( FileHandle, NULL, NULL, &SystemFileTime )); } else { return( FALSE); } }
|