www.pudn.com > NetPaw.rar > Crc32.cpp
#include "stdafx.h" #include "Crc32.h" #includeusing 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; }