243 lines
5.4 KiB
C++
243 lines
5.4 KiB
C++
typedef const char * LPCSTR;
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <memory.h>
|
|
#include "7zip.h"
|
|
|
|
C7zip::C7zip (LPCSTR FileName) :
|
|
m_FileSize(0),
|
|
m_CurrentFile(-1),
|
|
m_blockIndex(0xFFFFFFFF),
|
|
m_outBuffer(0),
|
|
m_outBufferSize(0),
|
|
m_NotfyCallback(NotfyCallbackDefault),
|
|
m_NotfyCallbackInfo(NULL),
|
|
m_db(NULL),
|
|
m_Opened(false)
|
|
{
|
|
memset(&m_FileName,0,sizeof(m_FileName));
|
|
memset(&m_archiveLookStream,0,sizeof(m_archiveLookStream));
|
|
|
|
m_db = new CSzArEx;
|
|
memset(m_db,0,sizeof(CSzArEx));
|
|
|
|
m_archiveStream.s.Read = SzFileReadImp;
|
|
m_archiveStream.s.Seek = SzFileSeekImp;
|
|
|
|
m_allocImp.Alloc = AllocAllocImp;
|
|
m_allocImp.Free = AllocFreeImp;
|
|
|
|
m_allocTempImp.Alloc = AllocAllocImp;
|
|
m_allocTempImp.Free = AllocFreeImp;
|
|
|
|
InFile_Open(&m_archiveStream.file,FileName);
|
|
if (m_archiveStream.file.handle == INVALID_HANDLE_VALUE)
|
|
{
|
|
//PrintError("can not open input file");
|
|
return;
|
|
}
|
|
m_FileSize = GetFileSize(m_archiveStream.file.handle,NULL);
|
|
|
|
char drive[_MAX_DRIVE] ,dir[_MAX_DIR], ext[_MAX_EXT];
|
|
_splitpath( FileName, drive, dir, m_FileName, ext );
|
|
|
|
CrcGenerateTable();
|
|
SzArEx_Init(m_db);
|
|
|
|
LookToRead_Init(&m_archiveLookStream);
|
|
LookToRead_CreateVTable(&m_archiveLookStream, False);
|
|
m_archiveLookStream.realStream = &m_archiveStream.s;
|
|
|
|
SRes res = SzArEx_Open(m_db, &m_archiveLookStream.s, &m_allocImp, &m_allocTempImp);
|
|
if (res == SZ_OK)
|
|
{
|
|
m_Opened = true;
|
|
}
|
|
else
|
|
{
|
|
//SzArEx_Open will delete the passed db if it fails
|
|
m_db = NULL;
|
|
}
|
|
}
|
|
|
|
C7zip::~C7zip (void)
|
|
{
|
|
if (m_db)
|
|
{
|
|
delete m_db;
|
|
m_db = NULL;
|
|
}
|
|
#ifdef tofix
|
|
SetNotificationCallback(NULL,NULL);
|
|
SzArDbExFree(&m_db, m_allocImp.Free);
|
|
|
|
if (m_archiveStream.File)
|
|
{
|
|
fclose(m_archiveStream.File);
|
|
}
|
|
if (m_outBuffer)
|
|
{
|
|
m_allocImp.Free(m_outBuffer);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void C7zip::SetNotificationCallback (LP7ZNOTIFICATION NotfyFnc, void * CBInfo)
|
|
{
|
|
m_NotfyCallback = NotfyFnc ? NotfyFnc : NotfyCallbackDefault;
|
|
m_NotfyCallbackInfo = CBInfo;
|
|
}
|
|
|
|
#ifdef tofix
|
|
void C7zip::StatusUpdate(_7Z_STATUS status, int Value1, int Value2, C7zip * _this )
|
|
{
|
|
CFileItem * File = _this->m_CurrentFile >= 0 ? _this->FileItem(_this->m_CurrentFile) : NULL;
|
|
|
|
switch (status)
|
|
{
|
|
case LZMADECODE_START: _this->m_NotfyCallback("Start decoding",_this->m_NotfyCallbackInfo); break;
|
|
case LZMADECODE_UPDATE:
|
|
{
|
|
char Msg[200];
|
|
sprintf(Msg,"decoding %s: %0.2f%%",File->Name, (Value1/(float)Value2) * 100);
|
|
_this->m_NotfyCallback(Msg,_this->m_NotfyCallbackInfo);
|
|
}
|
|
break;
|
|
case LZMADECODE_DONE: _this->m_NotfyCallback("Finished decoding",_this->m_NotfyCallbackInfo); break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool C7zip::GetFile(int index, Byte * Data, size_t DataLen )
|
|
{
|
|
m_CurrentFile = -1;
|
|
if (Data == NULL || DataLen == 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (m_archiveStream.file.handle == INVALID_HANDLE_VALUE)
|
|
{
|
|
return false;
|
|
}
|
|
m_CurrentFile = index;
|
|
|
|
size_t offset;
|
|
size_t outSizeProcessed;
|
|
|
|
wchar_t Msg[200];
|
|
std::wstring FileName = FileNameIndex(index);
|
|
_snwprintf(Msg, sizeof(Msg) / sizeof(Msg[0]), L"extracting %s", FileName.c_str());
|
|
m_NotfyCallback(Msg,m_NotfyCallbackInfo);
|
|
|
|
SRes res = SzArEx_Extract(m_db, &m_archiveLookStream.s, index,
|
|
&m_blockIndex, &m_outBuffer, &m_outBufferSize,
|
|
&offset, &outSizeProcessed,
|
|
&m_allocImp, &m_allocTempImp);
|
|
if (res != SZ_OK)
|
|
{
|
|
m_CurrentFile = -1;
|
|
return false;
|
|
}
|
|
|
|
if (DataLen < outSizeProcessed)
|
|
{
|
|
outSizeProcessed = DataLen;
|
|
}
|
|
memcpy(Data,m_outBuffer + offset,outSizeProcessed);
|
|
m_NotfyCallback(L"",m_NotfyCallbackInfo);
|
|
m_CurrentFile = -1;
|
|
return true;
|
|
}
|
|
|
|
void * C7zip::AllocAllocImp (void * /*p*/, size_t size)
|
|
{
|
|
return malloc(size);
|
|
//return new BYTE[size];
|
|
}
|
|
|
|
void C7zip::AllocFreeImp (void * /*p*/, void *address)
|
|
{
|
|
if (address != NULL)
|
|
{
|
|
free(address);
|
|
}
|
|
}
|
|
|
|
SRes C7zip::SzFileReadImp(void *object, void *buffer, size_t *processedSize)
|
|
{
|
|
CFileInStream *p = (CFileInStream *)object;
|
|
DWORD dwRead;
|
|
if (!ReadFile(p->file.handle,buffer,*processedSize,&dwRead,NULL))
|
|
{
|
|
return SZ_ERROR_FAIL;
|
|
}
|
|
//p->s.curpos += read_sz;
|
|
*processedSize = dwRead;
|
|
return SZ_OK;
|
|
}
|
|
|
|
SRes C7zip::SzFileSeekImp(void *p, Int64 *pos, ESzSeek origin)
|
|
{
|
|
CFileInStream *s = (CFileInStream *)p;
|
|
DWORD dwMoveMethod;
|
|
|
|
switch (origin)
|
|
{
|
|
case SZ_SEEK_SET:
|
|
dwMoveMethod = FILE_BEGIN;
|
|
break;
|
|
case SZ_SEEK_CUR:
|
|
dwMoveMethod = FILE_CURRENT;
|
|
break;
|
|
case SZ_SEEK_END:
|
|
dwMoveMethod = FILE_END;
|
|
break;
|
|
default:
|
|
return SZ_ERROR_FAIL;
|
|
|
|
}
|
|
*pos = SetFilePointer(s->file.handle,(LONG)*pos, NULL, dwMoveMethod);
|
|
if (*pos == INVALID_SET_FILE_POINTER)
|
|
{
|
|
return SZ_ERROR_FAIL;
|
|
}
|
|
return SZ_OK;
|
|
}
|
|
|
|
const char * C7zip::FileName ( char * FileName, int SizeOfFileName ) const
|
|
{
|
|
if (FileName == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
int Len = strlen(m_FileName);
|
|
if (Len > (SizeOfFileName - 1))
|
|
{
|
|
Len = (SizeOfFileName - 1);
|
|
}
|
|
strncpy(FileName,m_FileName,Len);
|
|
FileName[Len] = 0;
|
|
return FileName;
|
|
}
|
|
|
|
std::wstring C7zip::FileNameIndex (int index)
|
|
{
|
|
std::wstring filename;
|
|
if (m_db == NULL || m_db->FileNameOffsets == 0)
|
|
{
|
|
/* no filename */
|
|
return filename;
|
|
}
|
|
int namelen = SzArEx_GetFileNameUtf16(m_db, index, NULL);
|
|
if (namelen <= 0)
|
|
{
|
|
/* no filename */
|
|
return filename;
|
|
}
|
|
filename.resize(namelen);
|
|
SzArEx_GetFileNameUtf16(m_db, index, (UInt16 *)filename.c_str());
|
|
return filename;
|
|
}
|