#include "libNPK_StdAfx.h" #include "libNPK_FileStream.h" #include "libNPK_Errors.h" #include "libEncrypt_CRC32.h" namespace NPK { CFileStream::CFileStream(CNPKFile* pNPKFile, HANDLE hFile, const FileItemBaseInfo& baseFileInfo) : m_pNPKFile(pNPKFile) , m_hFileandle(hFile) , m_fileName(baseFileInfo.keyName) , m_fileOffset(baseFileInfo.fileOffset) , m_fileSize(baseFileInfo.fileSize) , m_currentOffset(0) { } CFileStream::~CFileStream() { } uint32_t CFileStream::read(void* buffer, uint32_t size) { if(isEOF()) { return 0; // End of file } DWORD dwOffset = m_fileOffset + m_currentOffset; if (dwOffset != ::SetFilePointer(m_hFileandle, dwOffset, NULL, FILE_BEGIN)) { setLastError(NPK_ERR_FILE_READ, "WinErr=%d", ::GetLastError()); return 0; // Failed to set file pointer } DWORD dwRemainBytes = m_fileSize - m_currentOffset; DWORD dwToRead = (size < dwRemainBytes) ? size : dwRemainBytes; DWORD dwBytesRead = 0; if(!::ReadFile(m_hFileandle, buffer, dwToRead, &dwBytesRead, NULL)) { setLastError(NPK_ERR_FILE_READ, "WinErr=%d", ::GetLastError()); return 0; // Failed to read file } m_currentOffset += dwBytesRead; return dwBytesRead; } bool CFileStream::seek(uint32_t offset) { if(offset > m_fileSize) { setLastError(NPK_ERR_FILE_READ, "Seek offset %u exceeds file size %u", offset, m_fileSize); return false; // Seek offset exceeds file size } m_currentOffset = offset; return true; } uint32_t CFileStream::crc32(void) { if (m_crc32Calculated) return m_crc32; // CRC32 already calculated const size_t kBufferSize = 1024*4; uint8_t pTempBuffer[kBufferSize]; uint32_t currentOffset = m_currentOffset; m_currentOffset = 0; m_crc32 = 0; // Read the entire file to calculate CRC32 uint32_t bytesRead = 0; while ((bytesRead = read(pTempBuffer, kBufferSize)) > 0) { m_crc32 = crcMemory32(pTempBuffer, bytesRead, m_crc32); } m_currentOffset = currentOffset; m_crc32Calculated = true; return m_crc32; } bool CFileStream::writeToDiskFile(const wchar_t* diskPathFile) { HANDLE hFile = ::CreateFileW(diskPathFile, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0); if (hFile == INVALID_HANDLE_VALUE) { setLastError(NPK_ERR_FILE_CREATE, "Failed to open output file for writing, LastError=%d.", ::GetLastError()); return false; // Failed to open output file } //store current read offset uint32_t currentOffset = m_currentOffset; m_currentOffset = 0; //read loop char buffer[4096] = { 0 }; uint32_t bytesRead = 0; while ((bytesRead = this->read(buffer, sizeof(buffer))) > 0) { DWORD dwWriteBytes = 0; if (!WriteFile(hFile, buffer, bytesRead, &dwWriteBytes, 0) || dwWriteBytes != bytesRead) { setLastError(NPK_ERR_FILE_WRITE, "Failed to write to output file, LastError=%d", ::GetLastError()); CloseHandle(hFile); m_currentOffset = currentOffset; return false; // Failed to write to output file } } CloseHandle(hFile); m_currentOffset = currentOffset; return true; } }