www.pudn.com > NetPaw.rar > Crc32.cpp


#include "stdafx.h" 
#include "Crc32.h" 
#include  
using namespace std; 
 
//*********************************************** 
CCrc32::CCrc32() : m_pdwCrc32Table(NULL) 
{ 
} 
 
//*********************************************** 
CCrc32::~CCrc32() 
{ 
	Free(); 
} 
 
//*********************************************** 
void CCrc32::Init(void) 
{ 
	// This is the official polynomial used by CRC32 in PKZip. 
	// Often times the polynomial shown reversed as 0x04C11DB7. 
	DWORD dwPolynomial = 0xEDB88320; 
	int i, j; 
 
	Free(); 
	m_pdwCrc32Table = new DWORD[256]; 
 
	DWORD dwCrc; 
	for(i = 0; i < 256; i++) 
	{ 
		dwCrc = i; 
		for(j = 8; j > 0; j--) 
		{ 
			if(dwCrc & 1) 
				dwCrc = (dwCrc >> 1) ^ dwPolynomial; 
			else 
				dwCrc >>= 1; 
		} 
		m_pdwCrc32Table[i] = dwCrc; 
	} 
} 
 
//*********************************************** 
void CCrc32::Free(void) 
{ 
	delete m_pdwCrc32Table; 
	m_pdwCrc32Table = NULL; 
} 
 
//*********************************************** 
inline void CCrc32::CalcCrc32(const BYTE byte, DWORD &dwCrc32) const 
{ 
	dwCrc32 = ((dwCrc32) >> 8) ^ m_pdwCrc32Table[(byte) ^ ((dwCrc32) & 0x000000FF)]; 
} 
 
//*********************************************** 
bool CCrc32::GetFileSizeQW(const HANDLE hFile, QWORD &qwSize) 
{ 
	_ASSERTE(hFile != INVALID_HANDLE_VALUE); 
 
	bool bSuccess = true; 
 
	try 
	{ 
		DWORD dwLo = 0, dwHi = 0; 
		dwLo = GetFileSize(hFile, &dwHi); 
 
		if(dwLo == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) 
		{ 
			bSuccess = false; 
			qwSize = 0; 
		} 
		else 
		{ 
			qwSize = MAKEQWORD(dwHi, dwLo); 
		} 
	} 
	catch(...) 
	{ 
		bSuccess = false; 
	} 
 
	return bSuccess; 
} 
 
//*********************************************** 
DWORD CCrc32::FileCrc32Filemap(LPCTSTR szFilename, DWORD &dwCrc32, LONGLONG nOffset) const 
{ 
	_ASSERTE(szFilename); 
	_ASSERTE(lstrlen(szFilename)); 
 
	DWORD dwErrorCode = NO_ERROR; 
	HANDLE hFile = NULL, hFilemap = NULL; 
	dwCrc32 = 0xFFFFFFFF; 
 
	try 
	{ 
		// Is the table initialized? 
		if(m_pdwCrc32Table == NULL) 
			throw (DWORD)0; 
 
		// Open the file 
		hFile = CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
			FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY 
			| FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); 
		if(hFile == INVALID_HANDLE_VALUE) 
		{ 
			dwErrorCode = GetLastError(); 
			throw dwErrorCode; 
		} 
 
		// Get the file size 
		QWORD qwFileSize = 0; 
		if( !GetFileSizeQW(hFile, qwFileSize) || qwFileSize == 0 ) 
		{ 
			dwErrorCode = ERROR_BAD_LENGTH; 
			throw dwErrorCode; 
		} 
 
		// Create the file mapping 
		hFilemap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 
			0, 0, NULL ); 
		if( hFilemap == NULL ) 
		{ 
			dwErrorCode = GetLastError(); 
			throw dwErrorCode; 
		} 
 
		DWORD dwByteCount, dwViewSize; 
		LPVOID pBaseAddress; 
		LPBYTE pByte; 
 
		// move the pointer to skip checking the first nOffset bytes 
		QWORD qwFileOffset = (QWORD)nOffset; 
		qwFileSize -= (QWORD)nOffset; 
 
		// Loop while we map a section of the file and CRC it 
		while( qwFileSize > 0 ) 
		{ 
			dwViewSize = (qwFileSize < MAX_VIEW_SIZE) ? LODWORD(qwFileSize) : MAX_VIEW_SIZE; 
 
			pBaseAddress = MapViewOfFile( hFilemap, FILE_MAP_READ, 
				HIDWORD(qwFileOffset), LODWORD(qwFileOffset), dwViewSize ); 
 
			dwByteCount = dwViewSize; 
			pByte = (LPBYTE)pBaseAddress; 
			while( dwByteCount-- > 0 ) 
			{ 
				CalcCrc32(*pByte, dwCrc32); 
				pByte++; 
			} 
 
			UnmapViewOfFile( pBaseAddress ); 
			qwFileOffset += dwViewSize; 
			qwFileSize -= dwViewSize; 
		} 
	} 
	catch(DWORD dwError) 
	{ 
		dwErrorCode = dwError; 
	} 
	catch(...) 
	{ 
		// An unknown exception happened, or the table isn't initialized 
		dwErrorCode = ERROR_CRC; 
	} 
 
	if(hFilemap != NULL) CloseHandle(hFilemap); 
	if(hFile != NULL) CloseHandle(hFile); 
	dwCrc32 = ~dwCrc32; 
 
	return dwErrorCode; 
} 
 
//*********************************************** 
DWORD CCrc32::FileCrc32Assembly(LPCTSTR szFilename, DWORD &dwCrc32, LONGLONG nOffset) const 
{ 
	_ASSERTE(szFilename); 
	_ASSERTE(lstrlen(szFilename)); 
 
	DWORD dwErrorCode = NO_ERROR; 
	HANDLE hFile = NULL; 
 
	dwCrc32 = 0xFFFFFFFF; 
 
	try 
	{ 
		// Is the table initialized? 
		if(m_pdwCrc32Table == NULL) 
			throw (DWORD)0; 
 
		// Open the file 
		hFile = CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
			FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY 
			| FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); 
		if(hFile == INVALID_HANDLE_VALUE) 
		{ 
			dwErrorCode = GetLastError(); 
			throw dwErrorCode; 
		} 
 
		// move the file pointer to skip checking the first nOffset bytes 
		if( nOffset != 0 ) 
		{ 
			SetFilePointerEx(hFile, *((LARGE_INTEGER *)&nOffset), NULL, FILE_BEGIN); 
		} 
 
		BYTE buffer[MAX_BUFFER]; 
		DWORD dwBytesRead; 
		while( ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL) && dwBytesRead ) 
		{ 
			// Register use: 
			//		eax - CRC32 value 
			//		ebx - a lot of things 
			//		ecx - CRC32 value 
			//		edx - address of end of buffer 
			//		esi - address of start of buffer 
			//		edi - CRC32 table 
			__asm 
			{ 
				// Save the esi and edi registers 
				push esi 
				push edi 
 
				mov eax, dwCrc32			// Load the pointer to dwCrc32 
				mov ecx, [eax]				// Dereference the pointer to load dwCrc32 
 
				mov ebx, this				// Load the CRC32 table 
				mov edi, [ebx]CCrc32.m_pdwCrc32Table 
 
				lea esi, buffer				// Load buffer 
				mov ebx, dwBytesRead		// Load dwBytesRead 
				lea edx, [esi + ebx]		// Calculate the end of the buffer 
 
			crc32loop: 
				xor eax, eax				// Clear the eax register 
				mov bl, byte ptr [esi]		// Load the current source byte 
				 
				mov al, cl					// Copy crc value into eax 
				inc esi						// Advance the source pointer 
 
				xor al, bl					// Create the index into the CRC32 table 
				shr ecx, 8 
 
				mov ebx, [edi + eax * 4]	// Get the value out of the table 
				xor ecx, ebx				// xor with the current byte 
 
				cmp edx, esi				// Have we reached the end of the buffer? 
				jne crc32loop 
 
				// Restore the edi and esi registers 
				pop edi 
				pop esi 
 
				mov eax, dwCrc32			// Load the pointer to dwCrc32 
				mov [eax], ecx				// Write the result 
			} 
		} 
	} 
	catch(DWORD dwError) 
	{ 
		dwErrorCode = dwError; 
	} 
	catch(...) 
	{ 
		// An unknown exception happened, or the table isn't initialized 
		dwErrorCode = ERROR_CRC; 
	} 
 
	if(hFile != NULL) CloseHandle(hFile); 
	dwCrc32 = ~dwCrc32; 
 
	return dwErrorCode; 
}