typedef const char * LPCSTR; #include #include #include #include #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; }