130 lines
3.0 KiB
C++
130 lines
3.0 KiB
C++
#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;
|
|
}
|
|
|
|
}
|