mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 18:07:07 -06:00
3.13
This commit is contained in:
7
7zip/Archive/Cab/Cab.def
Executable file
7
7zip/Archive/Cab/Cab.def
Executable file
@@ -0,0 +1,7 @@
|
||||
; Cab.def
|
||||
|
||||
LIBRARY cab.dll
|
||||
|
||||
EXPORTS
|
||||
CreateObject PRIVATE
|
||||
GetHandlerProperty PRIVATE
|
||||
325
7zip/Archive/Cab/Cab.dsp
Executable file
325
7zip/Archive/Cab/Cab.dsp
Executable file
@@ -0,0 +1,325 @@
|
||||
# Microsoft Developer Studio Project File - Name="Cab" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=Cab - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Cab.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "Cab.mak" CFG="Cab - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Cab - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "Cab - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Cab - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /Yu"StdAfx.h" /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Formats\cab.dll" /opt:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Formats\cab.dll" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Cab - Win32 Release"
|
||||
# Name "Cab - Win32 Debug"
|
||||
# Begin Group "Spec"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Cab.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\DllExports.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\NewHandler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\String.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\String.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\UTFConvert.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\UTFConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Vector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Vector.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Windows"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Windows\PropVariant.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Engine"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabCopyDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabCopyDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabHandler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabHeader.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabHeader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabIn.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabIn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabInBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabInBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabItem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXBitDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXConst.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXExtConst.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXi86Converter.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\LZXi86Converter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MSZipConst.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MSZipDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MSZipDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\MSZipExtConst.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "7zip Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\InBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\InBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LSBFDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LSBFDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OutBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OutBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Compress"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Group "LZ"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LZ\LZOutWindow.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\LZ\LZOutWindow.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cab.ico
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
||||
29
7zip/Archive/Cab/Cab.dsw
Executable file
29
7zip/Archive/Cab/Cab.dsw
Executable file
@@ -0,0 +1,29 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "Cab"=.\Cab.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
67
7zip/Archive/Cab/CabCopyDecoder.cpp
Executable file
67
7zip/Archive/Cab/CabCopyDecoder.cpp
Executable file
@@ -0,0 +1,67 @@
|
||||
// CabCopyDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CabCopyDecoder.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
static const UINT32 kBufferSize = 1 << 17;
|
||||
|
||||
/*
|
||||
void CCopyDecoder::ReleaseStreams()
|
||||
{
|
||||
m_InStream.ReleaseStream();
|
||||
m_OutStream.ReleaseStream();
|
||||
}
|
||||
*/
|
||||
class CCopyDecoderFlusher
|
||||
{
|
||||
CCopyDecoder *m_Decoder;
|
||||
public:
|
||||
CCopyDecoderFlusher(CCopyDecoder *aDecoder): m_Decoder(aDecoder) {}
|
||||
~CCopyDecoderFlusher()
|
||||
{
|
||||
m_Decoder->Flush();
|
||||
// m_Decoder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP CCopyDecoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
UINT64 size = *outSize;
|
||||
|
||||
m_InStream.Init(inStream, m_ReservedSize, m_NumInDataBlocks);
|
||||
m_OutStream.Init(outStream);
|
||||
CCopyDecoderFlusher decoderFlusher(this);
|
||||
|
||||
UINT64 nowPos64 = 0;
|
||||
while(nowPos64 < size)
|
||||
{
|
||||
UINT32 blockSize;
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InStream.ReadBlock(blockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw 123456;
|
||||
}
|
||||
for (UINT32 i = 0; i < blockSize; i++)
|
||||
m_OutStream.WriteByte(m_InStream.ReadByte());
|
||||
nowPos64 += blockSize;
|
||||
if (progress != NULL)
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
43
7zip/Archive/Cab/CabCopyDecoder.h
Executable file
43
7zip/Archive/Cab/CabCopyDecoder.h
Executable file
@@ -0,0 +1,43 @@
|
||||
// CabCopyDecoder.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_COPY_DECODER_H
|
||||
#define __ARCHIVE_CAB_COPY_DECODER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Common/OutBuffer.h"
|
||||
#include "CabInBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CCopyDecoder:
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CInBuffer m_InStream;
|
||||
COutBuffer m_OutStream;
|
||||
BYTE m_ReservedSize;
|
||||
UINT32 m_NumInDataBlocks;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
// void ReleaseStreams();
|
||||
HRESULT Flush() { return m_OutStream.Flush(); }
|
||||
void SetParams(BYTE reservedSize, UINT32 numInDataBlocks)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumInDataBlocks = numInDataBlocks;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
636
7zip/Archive/Cab/CabHandler.cpp
Executable file
636
7zip/Archive/Cab/CabHandler.cpp
Executable file
@@ -0,0 +1,636 @@
|
||||
// Cab/Handler.cpp
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
#include "Common/ComTry.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Time.h"
|
||||
|
||||
#include "CabCopyDecoder.h"
|
||||
#include "LZXDecoder.h"
|
||||
#include "MSZIPDecoder.h"
|
||||
|
||||
#include "CabHandler.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
STATPROPSTG kProperties[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
{ NULL, kpidIsFolder, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidLastWriteTime, VT_FILETIME},
|
||||
{ NULL, kpidAttributes, VT_UI4},
|
||||
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
// { NULL, kpidDictionarySize, VT_UI4},
|
||||
|
||||
{ NULL, kpidBlock, VT_UI4}
|
||||
};
|
||||
|
||||
static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||
|
||||
static const wchar_t *kMethods[] =
|
||||
{
|
||||
L"None",
|
||||
L"MSZip",
|
||||
L"Quantum",
|
||||
L"LZX"
|
||||
};
|
||||
|
||||
static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
|
||||
static const wchar_t *kUnknownMethod = L"Unknown";
|
||||
|
||||
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
value->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfProperties(UINT32 *numProperties)
|
||||
{
|
||||
*numProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetPropertyInfo(UINT32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
{
|
||||
if(index >= sizeof(kProperties) / sizeof(kProperties[0]))
|
||||
return E_INVALIDARG;
|
||||
const STATPROPSTG &srcItem = kProperties[index];
|
||||
*propID = srcItem.propid;
|
||||
*varType = srcItem.vt;
|
||||
*name = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UINT32 *numProperties)
|
||||
{
|
||||
*numProperties = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetArchivePropertyInfo(UINT32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
const CItem &fileInfo = m_Files[index];
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
if (fileInfo.IsNameUTF())
|
||||
{
|
||||
UString unicodeName;
|
||||
if (!ConvertUTF8ToUnicode(fileInfo.Name, unicodeName))
|
||||
propVariant = L"";
|
||||
else
|
||||
propVariant = unicodeName;
|
||||
}
|
||||
else
|
||||
propVariant = MultiByteToUnicodeString(fileInfo.Name, CP_ACP);
|
||||
break;
|
||||
case kpidIsFolder:
|
||||
propVariant = false;
|
||||
break;
|
||||
case kpidSize:
|
||||
propVariant = fileInfo.UnPackSize;
|
||||
break;
|
||||
case kpidLastWriteTime:
|
||||
{
|
||||
FILETIME localFileTime, utcFileTime;
|
||||
if (DosTimeToFileTime(fileInfo.Time, localFileTime))
|
||||
{
|
||||
if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
|
||||
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
|
||||
}
|
||||
else
|
||||
utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
|
||||
propVariant = utcFileTime;
|
||||
break;
|
||||
}
|
||||
case kpidAttributes:
|
||||
propVariant = fileInfo.GetWinAttributes();
|
||||
break;
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
UINT16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex(
|
||||
m_Folders.Size(), fileInfo.FolderIndex);
|
||||
const NHeader::CFolder &folder = m_Folders[realFolderIndex];
|
||||
UString method;
|
||||
int methodIndex = folder.GetCompressionMethod();
|
||||
if (methodIndex < kNumMethods)
|
||||
method = kMethods[methodIndex];
|
||||
else
|
||||
method = kUnknownMethod;
|
||||
if (methodIndex == NHeader::NCompressionMethodMajor::kLZX)
|
||||
{
|
||||
method += L":";
|
||||
wchar_t temp[32];
|
||||
_itow (folder.CompressionTypeMinor, temp, 10);
|
||||
method += temp;
|
||||
}
|
||||
propVariant = method;
|
||||
break;
|
||||
}
|
||||
case kpidBlock:
|
||||
propVariant = UINT32(fileInfo.FolderIndex);
|
||||
break;
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
class CPropgressImp: public CProgressVirt
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UINT64 *numFiles);
|
||||
STDMETHOD(SetCompleted)(const UINT64 *numFiles);
|
||||
void Init(IArchiveOpenCallback *openArchiveCallback)
|
||||
{ m_OpenArchiveCallback = openArchiveCallback; }
|
||||
};
|
||||
|
||||
STDMETHODIMP CPropgressImp::SetTotal(const UINT64 *numFiles)
|
||||
{
|
||||
if (m_OpenArchiveCallback)
|
||||
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CPropgressImp::SetCompleted(const UINT64 *numFiles)
|
||||
{
|
||||
if (m_OpenArchiveCallback)
|
||||
return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Open(IInStream *inStream,
|
||||
const UINT64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
m_Stream.Release();
|
||||
// try
|
||||
{
|
||||
CInArchive archive;
|
||||
m_Files.Clear();
|
||||
CPropgressImp progressImp;
|
||||
progressImp.Init(openArchiveCallback);
|
||||
RINOK(archive.Open(inStream, maxCheckStartPosition,
|
||||
m_ArchiveInfo, m_Folders, m_Files, &progressImp));
|
||||
m_Stream = inStream;
|
||||
}
|
||||
/*
|
||||
catch(...)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
*/
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
m_Stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CCabFolderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UINT32 size, UINT32 *processedSize);
|
||||
private:
|
||||
const CObjectVector<NHeader::CFolder> *m_Folders;
|
||||
const CObjectVector<CItem> *m_Files;
|
||||
const CRecordVector<int> *m_FileIndexes;
|
||||
const CRecordVector<bool> *m_ExtractStatuses;
|
||||
int m_StartIndex;
|
||||
int m_CurrentIndex;
|
||||
int m_NumFiles;
|
||||
UINT64 m_CurrentDataPos;
|
||||
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
|
||||
bool m_TestMode;
|
||||
|
||||
bool m_FileIsOpen;
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
UINT64 m_FilePos;
|
||||
|
||||
HRESULT OpenFile(int indexIndex, ISequentialOutStream **realOutStream);
|
||||
HRESULT WriteEmptyFiles();
|
||||
UINT64 m_StartImportantTotalUnPacked;
|
||||
public:
|
||||
void Init(
|
||||
const CObjectVector<NHeader::CFolder> *folders,
|
||||
const CObjectVector<CItem> *files,
|
||||
const CRecordVector<int> *fileIndices,
|
||||
const CRecordVector<bool> *extractStatuses,
|
||||
int startIndex,
|
||||
int numFiles,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
UINT64 startImportantTotalUnPacked,
|
||||
bool testMode);
|
||||
HRESULT FlushCorrupted();
|
||||
HRESULT Unsupported();
|
||||
};
|
||||
|
||||
void CCabFolderOutStream::Init(
|
||||
const CObjectVector<NHeader::CFolder> *folders,
|
||||
const CObjectVector<CItem> *files,
|
||||
const CRecordVector<int> *fileIndices,
|
||||
const CRecordVector<bool> *extractStatuses,
|
||||
int startIndex,
|
||||
int numFiles,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
UINT64 startImportantTotalUnPacked,
|
||||
bool testMode)
|
||||
{
|
||||
m_Folders = folders;
|
||||
m_Files = files;
|
||||
m_FileIndexes = fileIndices;
|
||||
m_ExtractStatuses = extractStatuses;
|
||||
m_StartIndex = startIndex;
|
||||
m_NumFiles = numFiles;
|
||||
m_ExtractCallback = extractCallback;
|
||||
m_StartImportantTotalUnPacked = startImportantTotalUnPacked;
|
||||
m_TestMode = testMode;
|
||||
|
||||
m_CurrentIndex = 0;
|
||||
m_FileIsOpen = false;
|
||||
}
|
||||
|
||||
HRESULT CCabFolderOutStream::OpenFile(int indexIndex, ISequentialOutStream **realOutStream)
|
||||
{
|
||||
// RINOK(m_ExtractCallback->SetCompleted(&m_StartImportantTotalUnPacked));
|
||||
|
||||
int fullIndex = m_StartIndex + indexIndex;
|
||||
|
||||
INT32 askMode;
|
||||
if((*m_ExtractStatuses)[fullIndex])
|
||||
askMode = m_TestMode ?
|
||||
NArchive::NExtract::NAskMode::kTest :
|
||||
NArchive::NExtract::NAskMode::kExtract;
|
||||
else
|
||||
askMode = NArchive::NExtract::NAskMode::kSkip;
|
||||
|
||||
int index = (*m_FileIndexes)[fullIndex];
|
||||
const CItem &fileInfo = (*m_Files)[index];
|
||||
UINT16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex(
|
||||
m_Folders->Size(), fileInfo.FolderIndex);
|
||||
|
||||
RINOK(m_ExtractCallback->GetStream(index, realOutStream, askMode));
|
||||
|
||||
UINT64 currentUnPackSize = fileInfo.UnPackSize;
|
||||
|
||||
bool mustBeProcessedAnywhere = (indexIndex < m_NumFiles - 1);
|
||||
|
||||
if (realOutStream || mustBeProcessedAnywhere)
|
||||
{
|
||||
if (!realOutStream && !m_TestMode)
|
||||
askMode = NArchive::NExtract::NAskMode::kSkip;
|
||||
RINOK(m_ExtractCallback->PrepareOperation(askMode));
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCabFolderOutStream::WriteEmptyFiles()
|
||||
{
|
||||
for(;m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
|
||||
{
|
||||
int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex];
|
||||
const CItem &fileInfo = (*m_Files)[index];
|
||||
if (fileInfo.UnPackSize != 0)
|
||||
return S_OK;
|
||||
realOutStream.Release();
|
||||
HRESULT result = OpenFile(m_CurrentIndex, &realOutStream);
|
||||
realOutStream.Release();
|
||||
if (result == S_FALSE)
|
||||
{
|
||||
}
|
||||
else if (result == S_OK)
|
||||
{
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
}
|
||||
else
|
||||
return result;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCabFolderOutStream::Write(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
{
|
||||
UINT32 processedSizeReal = 0;
|
||||
while(m_CurrentIndex < m_NumFiles)
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
{
|
||||
int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex];
|
||||
const CItem &fileInfo = (*m_Files)[index];
|
||||
UINT64 fileSize = fileInfo.UnPackSize;
|
||||
|
||||
UINT32 numBytesToWrite = (UINT32)MyMin(fileSize - m_FilePos,
|
||||
UINT64(size - processedSizeReal));
|
||||
|
||||
UINT32 processedSizeLocal;
|
||||
if (!realOutStream)
|
||||
{
|
||||
processedSizeLocal = numBytesToWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(realOutStream->Write((const BYTE *)data + processedSizeReal, numBytesToWrite, &processedSizeLocal));
|
||||
}
|
||||
m_FilePos += processedSizeLocal;
|
||||
processedSizeReal += processedSizeLocal;
|
||||
if (m_FilePos == fileInfo.UnPackSize)
|
||||
{
|
||||
realOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
m_FileIsOpen = false;
|
||||
m_CurrentIndex++;
|
||||
}
|
||||
if (processedSizeReal == size)
|
||||
{
|
||||
RINOK(WriteEmptyFiles());
|
||||
if (processedSize != NULL)
|
||||
*processedSize = processedSizeReal;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HRESULT result = OpenFile(m_CurrentIndex, &realOutStream);
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
m_FileIsOpen = true;
|
||||
m_FilePos = 0;
|
||||
}
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCabFolderOutStream::FlushCorrupted()
|
||||
{
|
||||
// UINT32 processedSizeReal = 0;
|
||||
while(m_CurrentIndex < m_NumFiles)
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
{
|
||||
int index = (*m_FileIndexes)[m_StartIndex + m_CurrentIndex];
|
||||
const CItem &fileInfo = (*m_Files)[index];
|
||||
UINT64 fileSize = fileInfo.UnPackSize;
|
||||
|
||||
realOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError));
|
||||
m_FileIsOpen = false;
|
||||
m_CurrentIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
HRESULT result = OpenFile(m_CurrentIndex, &realOutStream);
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
m_FileIsOpen = true;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CCabFolderOutStream::Unsupported()
|
||||
{
|
||||
while(m_CurrentIndex < m_NumFiles)
|
||||
{
|
||||
HRESULT result = OpenFile(m_CurrentIndex, &realOutStream);
|
||||
if (result != S_FALSE && result != S_OK)
|
||||
return result;
|
||||
realOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
m_CurrentIndex++;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCabFolderOutStream::WritePart(const void *data,
|
||||
UINT32 size, UINT32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UINT32* indices, UINT32 numItems,
|
||||
INT32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == UINT32(-1));
|
||||
if (allFilesMode)
|
||||
numItems = m_Files.Size();
|
||||
if(numItems == 0)
|
||||
return S_OK;
|
||||
bool testMode = (_aTestMode != 0);
|
||||
UINT64 censoredTotalUnPacked = 0, importantTotalUnPacked = 0;
|
||||
int lastIndex = 0;
|
||||
CRecordVector<int> folderIndexes;
|
||||
CRecordVector<int> importantIndices;
|
||||
CRecordVector<bool> extractStatuses;
|
||||
|
||||
UINT32 i;
|
||||
for(i = 0; i < numItems; i++)
|
||||
{
|
||||
int index = allFilesMode ? i : indices[i];
|
||||
const CItem &fileInfo = m_Files[index];
|
||||
censoredTotalUnPacked += fileInfo.UnPackSize;
|
||||
|
||||
int folderIndex = fileInfo.FolderIndex;
|
||||
if (folderIndexes.IsEmpty())
|
||||
folderIndexes.Add(folderIndex);
|
||||
else
|
||||
{
|
||||
if (folderIndex != folderIndexes.Back())
|
||||
folderIndexes.Add(folderIndex);
|
||||
}
|
||||
|
||||
for(int j = index - 1; j >= lastIndex; j--)
|
||||
if(m_Files[j].FolderIndex != folderIndex)
|
||||
break;
|
||||
for(j++; j <= index; j++)
|
||||
{
|
||||
const CItem &fileInfo = m_Files[j];
|
||||
importantTotalUnPacked += fileInfo.UnPackSize;
|
||||
importantIndices.Add(j);
|
||||
extractStatuses.Add(j == index);
|
||||
}
|
||||
lastIndex = index + 1;
|
||||
}
|
||||
|
||||
extractCallback->SetTotal(importantTotalUnPacked);
|
||||
UINT64 currentImportantTotalUnPacked = 0;
|
||||
UINT64 currentImportantTotalPacked = 0;
|
||||
|
||||
CCopyDecoder *storeDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressCoder> storeDecoder;
|
||||
|
||||
NMSZip::CDecoder *msZipDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressCoder> msZipDecoder;
|
||||
|
||||
NLZX::CDecoder *lzxDecoderSpec = NULL;
|
||||
CMyComPtr<ICompressCoder> lzxDecoder;
|
||||
|
||||
|
||||
int curImportantIndexIndex = 0;
|
||||
UINT64 totalFolderUnPacked;
|
||||
for(i = 0; i < (UINT32)folderIndexes.Size(); i++, currentImportantTotalUnPacked += totalFolderUnPacked)
|
||||
{
|
||||
int folderIndex = folderIndexes[i];
|
||||
UINT16 realFolderIndex = NHeader::NFolderIndex::GetRealFolderIndex(
|
||||
m_Folders.Size(), folderIndex);
|
||||
|
||||
RINOK(extractCallback->SetCompleted(¤tImportantTotalUnPacked));
|
||||
totalFolderUnPacked = 0;
|
||||
for (int j = curImportantIndexIndex; j < importantIndices.Size(); j++)
|
||||
{
|
||||
const CItem &fileInfo = m_Files[importantIndices[j]];
|
||||
if (fileInfo.FolderIndex != folderIndex)
|
||||
break;
|
||||
totalFolderUnPacked += fileInfo.UnPackSize;
|
||||
}
|
||||
|
||||
CCabFolderOutStream *cabFolderOutStream = new CCabFolderOutStream;
|
||||
CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
|
||||
|
||||
const NHeader::CFolder &folder = m_Folders[realFolderIndex];
|
||||
|
||||
cabFolderOutStream->Init(&m_Folders, &m_Files, &importantIndices,
|
||||
&extractStatuses, curImportantIndexIndex, j - curImportantIndexIndex,
|
||||
extractCallback, currentImportantTotalUnPacked,
|
||||
folder.GetCompressionMethod() == NHeader::NCompressionMethodMajor::kQuantum?
|
||||
true: testMode);
|
||||
|
||||
curImportantIndexIndex = j;
|
||||
|
||||
UINT64 pos = folder.DataStart; // test it (+ archiveStart)
|
||||
RINOK(m_Stream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
localProgressSpec->Init(extractCallback, false);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec =
|
||||
new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
localCompressProgressSpec->Init(progress,
|
||||
NULL, ¤tImportantTotalUnPacked);
|
||||
|
||||
BYTE reservedSize = m_ArchiveInfo.ReserveBlockPresent() ?
|
||||
m_ArchiveInfo.PerDataSizes.PerDatablockAreaSize : 0;
|
||||
|
||||
switch(folder.GetCompressionMethod())
|
||||
{
|
||||
case NHeader::NCompressionMethodMajor::kNone:
|
||||
{
|
||||
if(storeDecoderSpec == NULL)
|
||||
{
|
||||
storeDecoderSpec = new CCopyDecoder;
|
||||
storeDecoder = storeDecoderSpec;
|
||||
}
|
||||
try
|
||||
{
|
||||
storeDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks);
|
||||
RINOK(storeDecoder->Code(m_Stream, outStream,
|
||||
NULL, &totalFolderUnPacked, compressProgress));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(cabFolderOutStream->FlushCorrupted());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NHeader::NCompressionMethodMajor::kMSZip:
|
||||
{
|
||||
if(lzxDecoderSpec == NULL)
|
||||
{
|
||||
msZipDecoderSpec = new NMSZip::CDecoder;
|
||||
msZipDecoder = msZipDecoderSpec;
|
||||
}
|
||||
try
|
||||
{
|
||||
msZipDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks);
|
||||
RINOK(msZipDecoder->Code(m_Stream, outStream,
|
||||
NULL, &totalFolderUnPacked, compressProgress));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(cabFolderOutStream->FlushCorrupted());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NHeader::NCompressionMethodMajor::kLZX:
|
||||
{
|
||||
if(lzxDecoderSpec == NULL)
|
||||
{
|
||||
lzxDecoderSpec = new NLZX::CDecoder;
|
||||
lzxDecoder = lzxDecoderSpec;
|
||||
}
|
||||
try
|
||||
{
|
||||
lzxDecoderSpec->SetParams(reservedSize, folder.NumDataBlocks,
|
||||
folder.CompressionTypeMinor);
|
||||
RINOK(lzxDecoder->Code(m_Stream, outStream,
|
||||
NULL, &totalFolderUnPacked, compressProgress));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(cabFolderOutStream->FlushCorrupted());
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
RINOK(cabFolderOutStream->Unsupported());
|
||||
// return E_FAIL;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UINT32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems = m_Files.Size();
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
50
7zip/Archive/Cab/CabHandler.h
Executable file
50
7zip/Archive/Cab/CabHandler.h
Executable file
@@ -0,0 +1,50 @@
|
||||
// CabHandler.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __CAB_HANDLER_H
|
||||
#define __CAB_HANDLER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../IArchive.h"
|
||||
#include "CabIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Open)(IInStream *stream,
|
||||
const UINT64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback);
|
||||
STDMETHOD(Close)();
|
||||
STDMETHOD(GetNumberOfItems)(UINT32 *numItems);
|
||||
STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value);
|
||||
STDMETHOD(Extract)(const UINT32* indices, UINT32 numItems,
|
||||
INT32 testMode, IArchiveExtractCallback *extractCallback);
|
||||
|
||||
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
|
||||
|
||||
STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
|
||||
STDMETHOD(GetPropertyInfo)(UINT32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType);
|
||||
|
||||
STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties);
|
||||
STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType);
|
||||
|
||||
private:
|
||||
CObjectVector<NHeader::CFolder> m_Folders;
|
||||
CObjectVector<CItem> m_Files;
|
||||
CInArchiveInfo m_ArchiveInfo;
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
19
7zip/Archive/Cab/CabHeader.cpp
Executable file
19
7zip/Archive/Cab/CabHeader.cpp
Executable file
@@ -0,0 +1,19 @@
|
||||
// Archive/Cab/Header.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CabHeader.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NCab{
|
||||
namespace NHeader{
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
UINT32 kSignature = 0x4643534d + 1;
|
||||
static class CSignatureInitializer
|
||||
{ public: CSignatureInitializer() { kSignature--; }} g_SignatureInitializer;
|
||||
|
||||
}
|
||||
|
||||
}}}
|
||||
117
7zip/Archive/Cab/CabHeader.h
Executable file
117
7zip/Archive/Cab/CabHeader.h
Executable file
@@ -0,0 +1,117 @@
|
||||
// Archive/Cab/Header.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_HEADER_H
|
||||
#define __ARCHIVE_CAB_HEADER_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
|
||||
#pragma pack(push, PragmaCabHeaders)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NHeader{
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
extern UINT32 kSignature;
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const int kPrevCabinet = 0x0001;
|
||||
const int kNextCabinet = 0x0002;
|
||||
const int kReservePresent = 0x0004;
|
||||
}
|
||||
|
||||
struct CBlock
|
||||
{
|
||||
UINT32 Signature; /* cabinet file signature */
|
||||
UINT32 Reserved1; /* reserved */
|
||||
UINT32 Size; /* size of this cabinet file in bytes */
|
||||
UINT32 Reserved2; /* reserved */
|
||||
UINT32 FileOffset; /* offset of the first CFFILE entry */
|
||||
UINT32 Reserved3; /* reserved */
|
||||
BYTE VersionMinor; /* cabinet file format version, minor */
|
||||
BYTE VersionMajor; /* cabinet file format version, major */
|
||||
UINT16 NumFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
UINT16 NumFiles; /* number of CFFILE entries in this cabinet */
|
||||
UINT16 Flags; /* cabinet file option indicators */
|
||||
UINT16 SetID; /* must be the same for all cabinets in a set */
|
||||
UINT16 CabinetNumber; /* number of this cabinet file in a set */
|
||||
};
|
||||
|
||||
struct CPerDataSizes
|
||||
{
|
||||
UINT16 PerCabinetAreaSize; /* (optional) size of per-cabinet reserved area */
|
||||
BYTE PerFolderAreaSize; /* (optional) size of per-folder reserved area */
|
||||
BYTE PerDatablockAreaSize; /* (optional) size of per-datablock reserved area */
|
||||
};
|
||||
|
||||
/*
|
||||
BYTE abReserve[]; // (optional) per-cabinet reserved area
|
||||
BYTE szCabinetPrev[]; // (optional) name of previous cabinet file
|
||||
BYTE szDiskPrev[]; // (optional) name of previous disk
|
||||
BYTE szCabinetNext[]; // (optional) name of next cabinet file
|
||||
BYTE szDiskNext[]; // (optional) name of next disk
|
||||
*/
|
||||
}
|
||||
|
||||
namespace NCompressionMethodMajor
|
||||
{
|
||||
const BYTE kNone = 0;
|
||||
const BYTE kMSZip = 1;
|
||||
const BYTE kQuantum = 2;
|
||||
const BYTE kLZX = 3;
|
||||
}
|
||||
|
||||
struct CFolder
|
||||
{
|
||||
UINT32 DataStart; // offset of the first CFDATA block in this folder
|
||||
UINT16 NumDataBlocks; // number of CFDATA blocks in this folder
|
||||
BYTE CompressionTypeMajor;
|
||||
BYTE CompressionTypeMinor;
|
||||
// BYTE abReserve[]; // (optional) per-folder reserved area
|
||||
BYTE GetCompressionMethod() const { return CompressionTypeMajor & 0xF; }
|
||||
};
|
||||
|
||||
const int kFileNameIsUTFAttributeMask = 0x80;
|
||||
|
||||
namespace NFolderIndex
|
||||
{
|
||||
const int kContinuedFromPrev = 0xFFFD;
|
||||
const int kContinuedToNext = 0xFFFE;
|
||||
const int kContinuedPrevAndNext = 0xFFFF;
|
||||
inline UINT16 GetRealFolderIndex(UINT16 aNumFolders, UINT16 aFolderIndex)
|
||||
{
|
||||
switch(aFolderIndex)
|
||||
{
|
||||
case kContinuedFromPrev:
|
||||
return 0;
|
||||
case kContinuedToNext:
|
||||
case kContinuedPrevAndNext:
|
||||
return aNumFolders - 1;
|
||||
default:
|
||||
return aFolderIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CFile
|
||||
{
|
||||
UINT32 UnPackSize; /* uncompressed size of this file in bytes */
|
||||
UINT32 UnPackOffset; /* uncompressed offset of this file in the folder */
|
||||
UINT16 FolderIndex; /* index into the CFFOLDER area */
|
||||
UINT16 PureDate;
|
||||
UINT16 PureTime; /* Time */
|
||||
UINT16 Attributes; /* attribute flags for this file */
|
||||
//BYTE szName[]; /* name of this file */
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop, PragmaCabHeaders)
|
||||
|
||||
#endif
|
||||
189
7zip/Archive/Cab/CabIn.cpp
Executable file
189
7zip/Archive/Cab/CabIn.cpp
Executable file
@@ -0,0 +1,189 @@
|
||||
// Archive/CabIn.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "CabIn.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NCab{
|
||||
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UINT32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT SafeRead(IInStream *inStream, void *data, UINT32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void SafeInByteRead(CInBuffer &inBuffer, void *data, UINT32 size)
|
||||
{
|
||||
UINT32 realProcessedSize;
|
||||
inBuffer.ReadBytes(data, size, realProcessedSize);
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
}
|
||||
|
||||
static void SafeReadName(CInBuffer &inBuffer, AString &name)
|
||||
{
|
||||
name.Empty();
|
||||
while(true)
|
||||
{
|
||||
BYTE b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
if (b == 0)
|
||||
return;
|
||||
name += char(b);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream,
|
||||
const UINT64 *searchHeaderSizeLimit,
|
||||
CInArchiveInfo &inArchiveInfo,
|
||||
CObjectVector<NHeader::CFolder> &folders,
|
||||
CObjectVector<CItem> &files,
|
||||
CProgressVirt *progressVirt)
|
||||
{
|
||||
UINT64 startPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &startPosition));
|
||||
|
||||
NHeader::NArchive::CBlock archiveHeader;
|
||||
|
||||
{
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
UINT64 value = 0;
|
||||
const int kSignatureSize = sizeof(value);
|
||||
UINT64 kSignature64 = NHeader::NArchive::kSignature;
|
||||
while(true)
|
||||
{
|
||||
BYTE b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
return S_FALSE;
|
||||
value >>= 8;
|
||||
value |= ((UINT64)b) << ((kSignatureSize - 1) * 8);
|
||||
if (inBuffer.GetProcessedSize() >= kSignatureSize)
|
||||
{
|
||||
if (value == kSignature64)
|
||||
break;
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit))
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
startPosition += inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
}
|
||||
RINOK(inStream->Seek(startPosition, STREAM_SEEK_SET, NULL));
|
||||
RINOK(ReadBytes(inStream, &archiveHeader, sizeof(archiveHeader)));
|
||||
// if (archiveHeader.Signature != NHeader::NArchive::kSignature)
|
||||
// return S_FALSE;
|
||||
|
||||
if (archiveHeader.Reserved1 != 0 ||
|
||||
archiveHeader.Reserved2 != 0 ||
|
||||
archiveHeader.Reserved3 != 0)
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
|
||||
inArchiveInfo.VersionMinor = archiveHeader.VersionMinor;
|
||||
inArchiveInfo.VersionMajor = archiveHeader.VersionMajor;
|
||||
inArchiveInfo.NumFolders = archiveHeader.NumFolders;
|
||||
inArchiveInfo.NumFiles = archiveHeader.NumFiles;
|
||||
inArchiveInfo.Flags = archiveHeader.Flags;
|
||||
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(SafeRead(inStream, &inArchiveInfo.PerDataSizes,
|
||||
sizeof(inArchiveInfo.PerDataSizes)));
|
||||
RINOK(inStream->Seek(inArchiveInfo.PerDataSizes.PerCabinetAreaSize,
|
||||
STREAM_SEEK_CUR, NULL));
|
||||
}
|
||||
|
||||
{
|
||||
UINT64 foldersStartPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &foldersStartPosition));
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
|
||||
{
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousCabinetName);
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousDiskName);
|
||||
}
|
||||
if ((archiveHeader.Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0)
|
||||
{
|
||||
SafeReadName(inBuffer, inArchiveInfo.NextCabinetName);
|
||||
SafeReadName(inBuffer, inArchiveInfo.NextDiskName);
|
||||
}
|
||||
foldersStartPosition += inBuffer.GetProcessedSize();
|
||||
RINOK(inStream->Seek(foldersStartPosition, STREAM_SEEK_SET, NULL));
|
||||
}
|
||||
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = archiveHeader.NumFiles;
|
||||
RINOK(progressVirt->SetTotal(&numFiles));
|
||||
}
|
||||
folders.Clear();
|
||||
for(int i = 0; i < archiveHeader.NumFolders; i++)
|
||||
{
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = 0;
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
NHeader::CFolder folder;
|
||||
RINOK(SafeRead(inStream, &folder, sizeof(folder)));
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(inStream->Seek(
|
||||
inArchiveInfo.PerDataSizes.PerFolderAreaSize, STREAM_SEEK_CUR, NULL));
|
||||
}
|
||||
folder.DataStart += (UINT32)startPosition;
|
||||
folders.Add(folder);
|
||||
}
|
||||
|
||||
RINOK(inStream->Seek(startPosition + archiveHeader.FileOffset,
|
||||
STREAM_SEEK_SET, NULL));
|
||||
|
||||
CInBuffer inBuffer;
|
||||
inBuffer.Init(inStream);
|
||||
files.Clear();
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
for(i = 0; i < archiveHeader.NumFiles; i++)
|
||||
{
|
||||
NHeader::CFile fileHeader;
|
||||
SafeInByteRead(inBuffer, &fileHeader, sizeof(fileHeader));
|
||||
CItem item;
|
||||
item.UnPackSize = fileHeader.UnPackSize;
|
||||
item.UnPackOffset = fileHeader.UnPackOffset;
|
||||
item.FolderIndex = fileHeader.FolderIndex;
|
||||
item.Time = ((UINT32(fileHeader.PureDate) << 16)) | fileHeader.PureTime;
|
||||
item.Attributes = fileHeader.Attributes;
|
||||
SafeReadName(inBuffer, item.Name);
|
||||
files.Add(item);
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UINT64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
68
7zip/Archive/Cab/CabIn.h
Executable file
68
7zip/Archive/Cab/CabIn.h
Executable file
@@ -0,0 +1,68 @@
|
||||
// Archive/CabIn.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_IN_H
|
||||
#define __ARCHIVE_CAB_IN_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "CabHeader.h"
|
||||
#include "CabItem.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CInArchiveException
|
||||
{
|
||||
public:
|
||||
enum CCauseType
|
||||
{
|
||||
kUnexpectedEndOfArchive = 0,
|
||||
kIncorrectArchive,
|
||||
kUnsupported,
|
||||
} Cause;
|
||||
CInArchiveException(CCauseType cause) : Cause(cause) {}
|
||||
};
|
||||
|
||||
class CInArchiveInfo
|
||||
{
|
||||
public:
|
||||
UINT32 Size; /* size of this cabinet file in bytes */
|
||||
BYTE VersionMinor; /* cabinet file format version, minor */
|
||||
BYTE VersionMajor; /* cabinet file format version, major */
|
||||
UINT16 NumFolders; /* number of CFFOLDER entries in this cabinet */
|
||||
UINT16 NumFiles; /* number of CFFILE entries in this cabinet */
|
||||
UINT16 Flags; /* cabinet file option indicators */
|
||||
UINT16 SetID; /* must be the same for all cabinets in a set */
|
||||
UINT16 CabinetNumber; /* number of this cabinet file in a set */
|
||||
|
||||
bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }
|
||||
NHeader::NArchive::CPerDataSizes PerDataSizes;
|
||||
|
||||
AString PreviousCabinetName;
|
||||
AString PreviousDiskName;
|
||||
AString NextCabinetName;
|
||||
AString NextDiskName;
|
||||
};
|
||||
|
||||
class CProgressVirt
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UINT64 *numFiles) PURE;
|
||||
STDMETHOD(SetCompleted)(const UINT64 *numFiles) PURE;
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
public:
|
||||
HRESULT Open(IInStream *inStream,
|
||||
const UINT64 *searchHeaderSizeLimit,
|
||||
CInArchiveInfo &inArchiveInfo,
|
||||
CObjectVector<NHeader::CFolder> &folders,
|
||||
CObjectVector<CItem> &aFiles,
|
||||
CProgressVirt *aProgressVirt);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
153
7zip/Archive/Cab/CabInBuffer.cpp
Executable file
153
7zip/Archive/Cab/CabInBuffer.cpp
Executable file
@@ -0,0 +1,153 @@
|
||||
// Archive/CabInBuffer.cpp
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "CabInBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
#pragma pack(push, PragmaCabDataHeader)
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct CDataBlockHeader
|
||||
{
|
||||
UINT32 CheckSum; /* checksum of this CFDATA entry */
|
||||
UINT16 PackSize; /* number of compressed bytes in this block */
|
||||
UINT16 UnPackSize; /* number of uncompressed bytes in this block */
|
||||
// BYTE abReserve[]; /* (optional) per-datablock reserved area */
|
||||
// BYTE ab[cbData]; /* compressed data bytes */
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop, PragmaCabDataHeader)
|
||||
|
||||
CInBuffer::CInBuffer(UINT32 bufferSize):
|
||||
m_BufferSize(bufferSize),
|
||||
m_Stream(0)
|
||||
{
|
||||
m_Buffer = new BYTE[m_BufferSize];
|
||||
}
|
||||
|
||||
CInBuffer::~CInBuffer()
|
||||
{
|
||||
delete []m_Buffer;
|
||||
// ReleaseStream();
|
||||
}
|
||||
|
||||
void CInBuffer::Init(ISequentialInStream *inStream, BYTE reservedSize, UINT32 numBlocks)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumBlocks = numBlocks;
|
||||
m_CurrentBlockIndex = 0;
|
||||
// ReleaseStream();
|
||||
m_Stream = inStream;
|
||||
// m_Stream->AddRef();
|
||||
m_ProcessedSize = 0;
|
||||
m_Pos = 0;
|
||||
m_NumReadBytesInBuffer = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void CInBuffer::ReleaseStream()
|
||||
{
|
||||
if(m_Stream != 0)
|
||||
{
|
||||
m_Stream->Release();
|
||||
m_Stream = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
class CCheckSum
|
||||
{
|
||||
UINT32 m_Value;
|
||||
public:
|
||||
CCheckSum(): m_Value(0){};
|
||||
void Init() { m_Value = 0; }
|
||||
void Update(const void *data, UINT32 size);
|
||||
UINT32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum::Update(const void *data, UINT32 size)
|
||||
{
|
||||
UINT32 checkSum = m_Value;
|
||||
const BYTE *aDataPointer = (const BYTE *)data;
|
||||
int numUINT32Words = size / 4; // Number of ULONGs
|
||||
|
||||
// dataPointer += numUINT32Words * 4;
|
||||
|
||||
UINT32 temp;
|
||||
const UINT32 *aDataPointer32 = (const UINT32 *)data;
|
||||
while (numUINT32Words-- > 0)
|
||||
{
|
||||
// temp ^= *aDataPointer32++;
|
||||
temp = *aDataPointer++; // Get low-order byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 8); // Add 2nd byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 16); // Add 3nd byte
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 24); // Add 4th byte
|
||||
checkSum ^= temp; // Update checksum
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
switch (size % 4)
|
||||
{
|
||||
case 3:
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 16); // Add 3nd byte
|
||||
case 2:
|
||||
temp |= (((ULONG)(*aDataPointer++)) << 8); // Add 2nd byte
|
||||
case 1:
|
||||
temp |= *aDataPointer++; // Get low-order byte
|
||||
default:
|
||||
break;
|
||||
}
|
||||
checkSum ^= temp;
|
||||
m_Value = checkSum;
|
||||
}
|
||||
HRESULT CInBuffer::ReadBlock(UINT32 &uncompressedSize, bool &dataAreCorrect)
|
||||
{
|
||||
if (m_CurrentBlockIndex >= m_NumBlocks)
|
||||
throw "there is no more data blocks";
|
||||
|
||||
m_ProcessedSize += m_NumReadBytesInBuffer;
|
||||
|
||||
CDataBlockHeader dataBlockHeader;
|
||||
UINT32 numProcessedBytes;
|
||||
RINOK(m_Stream->Read(&dataBlockHeader, sizeof(dataBlockHeader), &numProcessedBytes));
|
||||
if (numProcessedBytes != sizeof(dataBlockHeader))
|
||||
throw "bad block";
|
||||
|
||||
if (m_ReservedSize != 0)
|
||||
{
|
||||
BYTE reservedArea[256];
|
||||
RINOK(m_Stream->Read(reservedArea, m_ReservedSize, &numProcessedBytes));
|
||||
if (numProcessedBytes != m_ReservedSize)
|
||||
throw "bad block";
|
||||
}
|
||||
|
||||
RINOK(m_Stream->Read(m_Buffer, dataBlockHeader.PackSize, &m_NumReadBytesInBuffer));
|
||||
if (m_NumReadBytesInBuffer != dataBlockHeader.PackSize)
|
||||
throw "bad block";
|
||||
|
||||
if (dataBlockHeader.CheckSum == 0)
|
||||
dataAreCorrect = true;
|
||||
{
|
||||
CCheckSum checkSum;
|
||||
checkSum.Update(m_Buffer, dataBlockHeader.PackSize);
|
||||
checkSum.Update(&dataBlockHeader.PackSize,
|
||||
sizeof(dataBlockHeader) - sizeof(dataBlockHeader.CheckSum));
|
||||
dataAreCorrect = (checkSum.GetResult() == dataBlockHeader.CheckSum);
|
||||
}
|
||||
|
||||
m_Pos = 0;
|
||||
uncompressedSize = dataBlockHeader.UnPackSize;
|
||||
|
||||
m_CurrentBlockIndex++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
62
7zip/Archive/Cab/CabInBuffer.h
Executable file
62
7zip/Archive/Cab/CabInBuffer.h
Executable file
@@ -0,0 +1,62 @@
|
||||
// Archive/CabInBuffer.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_INBUFFER_H
|
||||
#define __ARCHIVE_CAB_INBUFFER_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CInBuffer
|
||||
{
|
||||
UINT64 m_ProcessedSize;
|
||||
UINT32 m_Pos;
|
||||
UINT32 m_NumReadBytesInBuffer;
|
||||
BYTE *m_Buffer;
|
||||
ISequentialInStream *m_Stream;
|
||||
UINT32 m_BufferSize;
|
||||
|
||||
UINT32 m_NumBlocks;
|
||||
UINT32 m_CurrentBlockIndex;
|
||||
UINT32 m_ReservedSize;
|
||||
|
||||
public:
|
||||
CInBuffer(UINT32 bufferSize = 0x20000);
|
||||
~CInBuffer();
|
||||
|
||||
void Init(ISequentialInStream *inStream, BYTE reservedSize, UINT32 numBlocks);
|
||||
// void ReleaseStream();
|
||||
|
||||
bool ReadByte(BYTE &b)
|
||||
{
|
||||
if(m_Pos >= m_NumReadBytesInBuffer)
|
||||
return false;
|
||||
b = m_Buffer[m_Pos++];
|
||||
return true;
|
||||
}
|
||||
BYTE ReadByte()
|
||||
{
|
||||
if(m_Pos >= m_NumReadBytesInBuffer)
|
||||
return 0;
|
||||
return m_Buffer[m_Pos++];
|
||||
}
|
||||
/*
|
||||
void ReadBytes(void *data, UINT32 size, UINT32 &aProcessedSize)
|
||||
{
|
||||
BYTE *aDataPointer = (BYTE *)data;
|
||||
for(int i = 0; i < size; i++)
|
||||
if (!ReadByte(aDataPointer[i]))
|
||||
break;
|
||||
aProcessedSize = i;
|
||||
}
|
||||
*/
|
||||
HRESULT ReadBlock(UINT32 &uncompressedSize, bool &dataAreCorrect);
|
||||
UINT64 GetProcessedSize() const { return m_ProcessedSize + m_Pos; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
33
7zip/Archive/Cab/CabItem.h
Executable file
33
7zip/Archive/Cab/CabItem.h
Executable file
@@ -0,0 +1,33 @@
|
||||
// Archive/Cab/ItemInfo.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_RAR_ITEMINFO_H
|
||||
#define __ARCHIVE_RAR_ITEMINFO_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/String.h"
|
||||
#include "CabHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CItem
|
||||
{
|
||||
public:
|
||||
UINT16 Flags;
|
||||
UINT64 UnPackSize;
|
||||
UINT32 UnPackOffset;
|
||||
UINT16 FolderIndex;
|
||||
UINT32 Time;
|
||||
UINT16 Attributes;
|
||||
UINT32 GetWinAttributes() const { return Attributes & (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
|
||||
bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }
|
||||
AString Name;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
66
7zip/Archive/Cab/DllExports.cpp
Executable file
66
7zip/Archive/Cab/DllExports.cpp
Executable file
@@ -0,0 +1,66 @@
|
||||
// DLLExports.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#define INITGUID
|
||||
|
||||
#include "Common/ComTry.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "CabHandler.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110060000}
|
||||
DEFINE_GUID(CLSID_CCabHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
STDAPI CreateObject(
|
||||
const GUID *classID,
|
||||
const GUID *interfaceID,
|
||||
void **outObject)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*outObject = 0;
|
||||
if (*classID != CLSID_CCabHandler)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
if (*interfaceID != IID_IInArchive)
|
||||
return E_NOINTERFACE;
|
||||
CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NCab::CHandler;
|
||||
*outObject = inArchive.Detach();
|
||||
COM_TRY_END
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
|
||||
{
|
||||
NWindows::NCOM::CPropVariant propVariant;
|
||||
switch(propID)
|
||||
{
|
||||
case NArchive::kName:
|
||||
propVariant = L"Cab";
|
||||
break;
|
||||
case NArchive::kClassID:
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(
|
||||
(const char *)&CLSID_CCabHandler, sizeof(GUID))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
case NArchive::kExtension:
|
||||
propVariant = L"cab";
|
||||
break;
|
||||
case NArchive::kUpdate:
|
||||
propVariant = false;
|
||||
break;
|
||||
case NArchive::kKeepName:
|
||||
propVariant = false;
|
||||
break;
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
112
7zip/Archive/Cab/LZXBitDecoder.h
Executable file
112
7zip/Archive/Cab/LZXBitDecoder.h
Executable file
@@ -0,0 +1,112 @@
|
||||
// Archive/Cab/LZXBitDecoder.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_LZXBITDECODER_H
|
||||
#define __ARCHIVE_CAB_LZXBITDECODER_H
|
||||
|
||||
#include "CabInBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
namespace NBitStream {
|
||||
|
||||
const int kNumBigValueBits = 8 * 4;
|
||||
|
||||
const int kNumValueBits = 17;
|
||||
const int kBitDecoderValueMask = (1 << kNumValueBits) - 1;
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
protected:
|
||||
CInBuffer m_Stream;
|
||||
UINT32 m_BitPos;
|
||||
UINT32 m_Value;
|
||||
public:
|
||||
void InitStream(ISequentialInStream *aStream, BYTE aReservedSize, UINT32 aNumBlocks)
|
||||
{
|
||||
m_Stream.Init(aStream, aReservedSize, aNumBlocks);
|
||||
}
|
||||
/*
|
||||
void ReleaseStream()
|
||||
{ m_Stream.ReleaseStream(); }
|
||||
*/
|
||||
UINT64 GetProcessedSize() const
|
||||
{ return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }
|
||||
UINT32 GetBitPosition() const
|
||||
{ return UINT32(m_Stream.GetProcessedSize() * 8 - (kNumBigValueBits - m_BitPos)); }
|
||||
|
||||
void Init()
|
||||
{
|
||||
m_BitPos = kNumBigValueBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
for (;m_BitPos >= 16; m_BitPos -= 16)
|
||||
{
|
||||
BYTE aByte0 = m_Stream.ReadByte();
|
||||
BYTE aByte1 = m_Stream.ReadByte();
|
||||
m_Value = (m_Value << 8) | aByte1;
|
||||
m_Value = (m_Value << 8) | aByte0;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 GetValue(UINT32 aNumBits)
|
||||
{
|
||||
return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >>
|
||||
(kNumValueBits - aNumBits);
|
||||
}
|
||||
|
||||
void MovePos(UINT32 aNumBits)
|
||||
{
|
||||
m_BitPos += aNumBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
UINT32 ReadBits(UINT32 aNumBits)
|
||||
{
|
||||
UINT32 aRes = GetValue(aNumBits);
|
||||
MovePos(aNumBits);
|
||||
return aRes;
|
||||
}
|
||||
UINT32 ReadBitsBig(UINT32 aNumBits)
|
||||
{
|
||||
UINT32 aNumBits0 = aNumBits / 2;
|
||||
UINT32 aNumBits1 = aNumBits - aNumBits0;
|
||||
UINT32 aRes = ReadBits(aNumBits0) << aNumBits1;
|
||||
return aRes + ReadBits(aNumBits1);
|
||||
}
|
||||
|
||||
BYTE DirectReadByte()
|
||||
{
|
||||
if (m_BitPos == kNumBigValueBits)
|
||||
return m_Stream.ReadByte();
|
||||
BYTE aRes;
|
||||
switch(m_BitPos)
|
||||
{
|
||||
case 0:
|
||||
aRes = BYTE(m_Value >> 16);
|
||||
break;
|
||||
case 8:
|
||||
aRes = BYTE(m_Value >> 24);
|
||||
break;
|
||||
case 16:
|
||||
aRes = BYTE(m_Value);
|
||||
break;
|
||||
case 24:
|
||||
aRes = BYTE(m_Value >> 8);
|
||||
break;
|
||||
}
|
||||
m_BitPos += 8;
|
||||
return aRes;
|
||||
}
|
||||
|
||||
HRESULT ReadBlock(UINT32 &anUncompressedSize, bool &aDataAreCorrect)
|
||||
{ return m_Stream.ReadBlock(anUncompressedSize, aDataAreCorrect); }
|
||||
};
|
||||
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
112
7zip/Archive/Cab/LZXConst.h
Executable file
112
7zip/Archive/Cab/LZXConst.h
Executable file
@@ -0,0 +1,112 @@
|
||||
// Archive/Cab/LZXConst.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_LZXCONST_H
|
||||
#define __ARCHIVE_CAB_LZXCONST_H
|
||||
|
||||
#include "LZXExtConst.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
|
||||
namespace NBlockType
|
||||
{
|
||||
const int kNumBits = 3;
|
||||
enum EEnum
|
||||
{
|
||||
kVerbatim = 1,
|
||||
kAligned = 2,
|
||||
kUncompressed = 3
|
||||
};
|
||||
}
|
||||
|
||||
const int kUncompressedBlockSizeNumBits = 24;
|
||||
|
||||
const UINT32 kLevelTableSize = 20;
|
||||
|
||||
const UINT32 kNumBitsForPreTreeLevel = 4;
|
||||
|
||||
const int kLevelSymbolZeros = 17;
|
||||
const int kLevelSymbolZerosBig = 18;
|
||||
const int kLevelSymbolSame = 19;
|
||||
|
||||
const int kLevelSymbolZerosStartValue = 4;
|
||||
const int kLevelSymbolZerosNumBits = 4;
|
||||
|
||||
const int kLevelSymbolZerosBigStartValue = kLevelSymbolZerosStartValue +
|
||||
(1 << kLevelSymbolZerosNumBits);
|
||||
const int kLevelSymbolZerosBigNumBits = 5;
|
||||
|
||||
const int kNumBitsForAlignLevel = 3;
|
||||
|
||||
const int kLevelSymbolSameNumBits = 1;
|
||||
const int kLevelSymbolSameStartValue = 4;
|
||||
|
||||
// const UINT32 kMainTableSize = 256 + kNumPosLenSlots + 1;
|
||||
|
||||
/*
|
||||
const UINT32 kLenTableSize = 28;
|
||||
|
||||
const UINT32 kLenTableStart = kMainTableSize;
|
||||
const UINT32 kAlignTableStart = kLenTableStart + kLenTableSize;
|
||||
|
||||
const UINT32 kHeapTablesSizesSum = kMainTableSize + kLenTableSize + kAlignTableSize;
|
||||
|
||||
|
||||
const UINT32 kMaxTableSize = kHeapTablesSizesSum;
|
||||
|
||||
const UINT32 kTableDirectLevels = 16;
|
||||
const UINT32 kTableLevelRepNumber = kTableDirectLevels;
|
||||
const UINT32 kTableLevel0Number = kTableLevelRepNumber + 1;
|
||||
const UINT32 kTableLevel0Number2 = kTableLevel0Number + 1;
|
||||
|
||||
const UINT32 kLevelMask = 0xF;
|
||||
|
||||
const UINT32 kPosLenNumber = 256;
|
||||
const UINT32 kReadTableNumber = 256 + kNumPosLenSlots;
|
||||
|
||||
//const UINT32 kMatchNumber = kReadTableNumber + 1;
|
||||
|
||||
const BYTE kLenStart[kLenTableSize] =
|
||||
{0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
|
||||
const BYTE kLenDirectBits[kLenTableSize] =
|
||||
{0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
|
||||
*/
|
||||
|
||||
const UINT32 kDistStart[] =
|
||||
{ 0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
|
||||
1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,65536,98304,131072,196608,
|
||||
0x40000,
|
||||
0x60000,
|
||||
0x80000,
|
||||
0xA0000,
|
||||
0xC0000,
|
||||
0xE0000,
|
||||
|
||||
0x100000,
|
||||
0x120000,
|
||||
0x140000,
|
||||
0x160000,
|
||||
0x180000,
|
||||
0x1A0000,
|
||||
0x1C0000,
|
||||
0x1E0000
|
||||
};
|
||||
const BYTE kDistDirectBits[] =
|
||||
{
|
||||
0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,
|
||||
17, 17, 17, 17, 17, 17,
|
||||
17, 17,17, 17, 17, 17, 17, 17
|
||||
};
|
||||
|
||||
/*
|
||||
const BYTE kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
|
||||
|
||||
const UINT32 kDistLimit2 = 0x101 - 1;
|
||||
*/
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
311
7zip/Archive/Cab/LZXDecoder.cpp
Executable file
311
7zip/Archive/Cab/LZXDecoder.cpp
Executable file
@@ -0,0 +1,311 @@
|
||||
// Archive/Cab/LZXDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LZXDecoder.h"
|
||||
|
||||
#include "LZXConst.h"
|
||||
#include "Common/Defs.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
static const UINT32 kHistorySize = (1 << 21);
|
||||
|
||||
const int kMainTableSize = 256 + kNumPosSlotLenSlotSymbols;
|
||||
|
||||
CDecoder::CDecoder():
|
||||
m_MainDecoder(kMainTableSize),
|
||||
m_LenDecoder(kNumLenSymbols),
|
||||
m_AlignDecoder(kAlignTableSize),
|
||||
m_LevelDecoder(kLevelTableSize)
|
||||
{
|
||||
m_OutWindowStream.Create(kHistorySize);
|
||||
m_i86TranslationOutStreamSpec = new Ci86TranslationOutStream;
|
||||
m_i86TranslationOutStream = m_i86TranslationOutStreamSpec;
|
||||
}
|
||||
|
||||
void CDecoder::ReleaseStreams()
|
||||
{
|
||||
// m_OutWindowStream.ReleaseStream();
|
||||
// m_InBitStream.ReleaseStream();
|
||||
m_i86TranslationOutStreamSpec->ReleaseStream();
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::Flush()
|
||||
{
|
||||
RINOK(m_OutWindowStream.Flush());
|
||||
return m_i86TranslationOutStreamSpec->Flush();
|
||||
}
|
||||
|
||||
void CDecoder::ReadTable(BYTE *lastLevels, BYTE *newLevels, UINT32 numSymbols)
|
||||
{
|
||||
BYTE levelLevels[kLevelTableSize];
|
||||
UINT32 i;
|
||||
for (i = 0; i < kLevelTableSize; i++)
|
||||
levelLevels[i] = BYTE(m_InBitStream.ReadBits(kNumBitsForPreTreeLevel));
|
||||
m_LevelDecoder.SetCodeLengths(levelLevels);
|
||||
for (i = 0; i < numSymbols;)
|
||||
{
|
||||
UINT32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (number <= kNumHuffmanBits)
|
||||
newLevels[i++] = BYTE((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1));
|
||||
else if (number == kLevelSymbolZeros || number == kLevelSymbolZerosBig)
|
||||
{
|
||||
int num;
|
||||
if (number == kLevelSymbolZeros)
|
||||
num = kLevelSymbolZerosStartValue +
|
||||
m_InBitStream.ReadBits(kLevelSymbolZerosNumBits);
|
||||
else
|
||||
num = kLevelSymbolZerosBigStartValue +
|
||||
m_InBitStream.ReadBits(kLevelSymbolZerosBigNumBits);
|
||||
for (;num > 0 && i < numSymbols; num--, i++)
|
||||
newLevels[i] = 0;
|
||||
}
|
||||
else if (number == kLevelSymbolSame)
|
||||
{
|
||||
int num = kLevelSymbolSameStartValue + m_InBitStream.ReadBits(kLevelSymbolSameNumBits);
|
||||
UINT32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (number > kNumHuffmanBits)
|
||||
throw "bad data";
|
||||
BYTE symbol = BYTE((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1));
|
||||
for (; num > 0 && i < numSymbols; num--, i++)
|
||||
newLevels[i] = symbol;
|
||||
}
|
||||
else
|
||||
throw "bad data";
|
||||
}
|
||||
|
||||
memmove(lastLevels, newLevels, numSymbols);
|
||||
}
|
||||
|
||||
void CDecoder::ReadTables(void)
|
||||
{
|
||||
int blockType = m_InBitStream.ReadBits(NBlockType::kNumBits);
|
||||
|
||||
if (blockType != NBlockType::kVerbatim && blockType != NBlockType::kAligned &&
|
||||
blockType != NBlockType::kUncompressed)
|
||||
throw "bad data";
|
||||
|
||||
m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
|
||||
|
||||
if (blockType == NBlockType::kUncompressed)
|
||||
{
|
||||
m_UncompressedBlock = true;
|
||||
UINT32 bitPos = m_InBitStream.GetBitPosition() % 16;
|
||||
m_InBitStream.ReadBits(16 - bitPos);
|
||||
for (int i = 0; i < kNumRepDistances; i++)
|
||||
{
|
||||
m_RepDistances[i] = 0;
|
||||
for (int j = 0; j < 4; j++)
|
||||
m_RepDistances[i] |= (m_InBitStream.DirectReadByte()) << (8 * j);
|
||||
m_RepDistances[i]--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_UncompressedBlock = false;
|
||||
|
||||
m_AlignIsUsed = (blockType == NBlockType::kAligned);
|
||||
|
||||
BYTE newLevels[kMaxTableSize];
|
||||
|
||||
if (m_AlignIsUsed)
|
||||
{
|
||||
for(int i = 0; i < kAlignTableSize; i++)
|
||||
newLevels[i] = m_InBitStream.ReadBits(kNumBitsForAlignLevel);
|
||||
m_AlignDecoder.SetCodeLengths(newLevels);
|
||||
}
|
||||
|
||||
ReadTable(m_LastByteLevels, newLevels, 256);
|
||||
ReadTable(m_LastPosLenLevels, newLevels + 256, m_NumPosLenSlots);
|
||||
for (int i = m_NumPosLenSlots; i < kNumPosSlotLenSlotSymbols; i++)
|
||||
newLevels[256 + i] = 0;
|
||||
m_MainDecoder.SetCodeLengths(newLevels);
|
||||
|
||||
ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols);
|
||||
m_LenDecoder.SetCodeLengths(newLevels);
|
||||
|
||||
}
|
||||
|
||||
class CDecoderFlusher
|
||||
{
|
||||
CDecoder *m_Decoder;
|
||||
public:
|
||||
CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder) {}
|
||||
~CDecoderFlusher()
|
||||
{
|
||||
m_Decoder->Flush();
|
||||
m_Decoder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void CDecoder::ClearPrevLeveles()
|
||||
{
|
||||
memset(m_LastByteLevels, 0, 256);
|
||||
memset(m_LastPosLenLevels, 0, kNumPosSlotLenSlotSymbols);
|
||||
memset(m_LastLenLevels, 0, kNumLenSymbols);
|
||||
};
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
UINT64 size = *outSize;
|
||||
|
||||
|
||||
m_OutWindowStream.Init(m_i86TranslationOutStream);
|
||||
m_InBitStream.InitStream(inStream, m_ReservedSize, m_NumInDataBlocks);
|
||||
|
||||
CDecoderFlusher flusher(this);
|
||||
|
||||
UINT32 uncompressedCFDataBlockSize;
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw "Data Error";
|
||||
}
|
||||
UINT32 uncompressedCFDataCurrentValue = 0;
|
||||
m_InBitStream.Init();
|
||||
|
||||
ClearPrevLeveles();
|
||||
|
||||
if (m_InBitStream.ReadBits(1) == 0)
|
||||
m_i86TranslationOutStreamSpec->Init(outStream, false, 0);
|
||||
else
|
||||
{
|
||||
UINT32 i86TranslationSize = m_InBitStream.ReadBits(16) << 16;
|
||||
i86TranslationSize |= m_InBitStream.ReadBits(16);
|
||||
m_i86TranslationOutStreamSpec->Init(outStream, true , i86TranslationSize);
|
||||
}
|
||||
|
||||
for(int i = 0 ; i < kNumRepDistances; i++)
|
||||
m_RepDistances[i] = 0;
|
||||
|
||||
UINT64 nowPos64 = 0;
|
||||
while(nowPos64 < size)
|
||||
{
|
||||
if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize)
|
||||
{
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw "Data Error";
|
||||
}
|
||||
m_InBitStream.Init();
|
||||
uncompressedCFDataCurrentValue = 0;
|
||||
}
|
||||
ReadTables();
|
||||
UINT32 nowPos = 0;
|
||||
UINT32 next = (UINT32)MyMin((UINT64)m_UnCompressedBlockSize, size - nowPos64);
|
||||
if (m_UncompressedBlock)
|
||||
{
|
||||
while(nowPos < next)
|
||||
{
|
||||
m_OutWindowStream.PutOneByte(m_InBitStream.DirectReadByte());
|
||||
nowPos++;
|
||||
uncompressedCFDataCurrentValue++;
|
||||
if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize)
|
||||
{
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw "Data Error";
|
||||
}
|
||||
// m_InBitStream.Init();
|
||||
uncompressedCFDataCurrentValue = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int bitPos = m_InBitStream.GetBitPosition() % 16;
|
||||
if (bitPos == 8)
|
||||
m_InBitStream.DirectReadByte();
|
||||
m_InBitStream.Normalize();
|
||||
}
|
||||
else for (;nowPos < next;)
|
||||
{
|
||||
if (uncompressedCFDataCurrentValue == uncompressedCFDataBlockSize)
|
||||
{
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw "Data Error";
|
||||
}
|
||||
m_InBitStream.Init();
|
||||
uncompressedCFDataCurrentValue = 0;
|
||||
}
|
||||
UINT32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (number < 256)
|
||||
{
|
||||
m_OutWindowStream.PutOneByte(BYTE(number));
|
||||
nowPos++;
|
||||
uncompressedCFDataCurrentValue++;
|
||||
// continue;
|
||||
}
|
||||
else if (number < 256 + m_NumPosLenSlots)
|
||||
{
|
||||
UINT32 posLenSlot = number - 256;
|
||||
UINT32 posSlot = posLenSlot / kNumLenSlots;
|
||||
UINT32 lenSlot = posLenSlot % kNumLenSlots;
|
||||
UINT32 length = 2 + lenSlot;
|
||||
if (lenSlot == kNumLenSlots - 1)
|
||||
length += m_LenDecoder.DecodeSymbol(&m_InBitStream);
|
||||
|
||||
if (posSlot < kNumRepDistances)
|
||||
{
|
||||
UINT32 distance = m_RepDistances[posSlot];
|
||||
m_OutWindowStream.CopyBackBlock(distance, length);
|
||||
if (posSlot != 0)
|
||||
{
|
||||
m_RepDistances[posSlot] = m_RepDistances[0];
|
||||
m_RepDistances[0] = distance;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 pos = kDistStart[posSlot];
|
||||
UINT32 posDirectBits = kDistDirectBits[posSlot];
|
||||
if (m_AlignIsUsed && posDirectBits >= kNumAlignBits)
|
||||
{
|
||||
pos += (m_InBitStream.ReadBits(posDirectBits - kNumAlignBits) << kNumAlignBits);
|
||||
pos += m_AlignDecoder.DecodeSymbol(&m_InBitStream);
|
||||
}
|
||||
else
|
||||
pos += m_InBitStream.ReadBits(posDirectBits);
|
||||
UINT32 distance = pos - kNumRepDistances;
|
||||
if (distance >= nowPos64 + nowPos)
|
||||
throw 777123;
|
||||
m_OutWindowStream.CopyBackBlock(distance, length);
|
||||
m_RepDistances[2] = m_RepDistances[1];
|
||||
m_RepDistances[1] = m_RepDistances[0];
|
||||
m_RepDistances[0] = distance;
|
||||
}
|
||||
nowPos += length;
|
||||
uncompressedCFDataCurrentValue += length;
|
||||
}
|
||||
else
|
||||
throw 98112823;
|
||||
}
|
||||
if (progress != NULL)
|
||||
{
|
||||
UINT64 inSize = m_InBitStream.GetProcessedSize();
|
||||
UINT64 outSize = nowPos64 + nowPos;
|
||||
RINOK(progress->SetRatioInfo(&inSize, &outSize));
|
||||
}
|
||||
nowPos64 += nowPos;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}}
|
||||
98
7zip/Archive/Cab/LZXDecoder.h
Executable file
98
7zip/Archive/Cab/LZXDecoder.h
Executable file
@@ -0,0 +1,98 @@
|
||||
// Archive/Cab/LZXDecoder.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_LZXDECODER_H
|
||||
#define __ARCHIVE_CAB_LZXDECODER_H
|
||||
|
||||
#include "../../ICoder.h"
|
||||
|
||||
#include "../../Compress/Huffman/HuffmanDecoder.h"
|
||||
#include "../../Compress/LZ/LZOutWindow.h"
|
||||
|
||||
#include "LZXExtConst.h"
|
||||
#include "LZXBitDecoder.h"
|
||||
|
||||
#include "LZXi86Converter.h"
|
||||
|
||||
// #include "../../../Projects/CompressInterface/CompressInterface.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
typedef NCompress::NHuffman::CDecoder<kNumHuffmanBits> CMSBFHuffmanDecoder;
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
NBitStream::CDecoder m_InBitStream;
|
||||
|
||||
CMSBFHuffmanDecoder m_MainDecoder;
|
||||
CMSBFHuffmanDecoder m_LenDecoder; // for matches with repeated offsets
|
||||
CMSBFHuffmanDecoder m_AlignDecoder; // for matches with repeated offsets
|
||||
CMSBFHuffmanDecoder m_LevelDecoder; // table for decoding other tables;
|
||||
|
||||
UINT32 m_RepDistances[kNumRepDistances];
|
||||
|
||||
BYTE m_LastByteLevels[256];
|
||||
BYTE m_LastPosLenLevels[kNumPosSlotLenSlotSymbols];
|
||||
BYTE m_LastLenLevels[kNumLenSymbols];
|
||||
|
||||
UINT32 m_DictionarySizePowerOf2;
|
||||
UINT32 m_NumPosSlots;
|
||||
UINT32 m_NumPosLenSlots;
|
||||
|
||||
// bool m_i86PreprocessingUsed;
|
||||
// UINT32 m_i86TranslationSize;
|
||||
|
||||
bool m_UncompressedBlock;
|
||||
bool m_AlignIsUsed;
|
||||
|
||||
UINT32 m_UnCompressedBlockSize;
|
||||
|
||||
Ci86TranslationOutStream *m_i86TranslationOutStreamSpec;
|
||||
CMyComPtr<ISequentialOutStream> m_i86TranslationOutStream;
|
||||
|
||||
BYTE m_ReservedSize;
|
||||
UINT32 m_NumInDataBlocks;
|
||||
|
||||
void ReadTable(BYTE *lastLevels, BYTE *newLevels, UINT32 numSymbols);
|
||||
void ReadTables();
|
||||
void ClearPrevLeveles();
|
||||
|
||||
public:
|
||||
CDecoder();
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
void ReleaseStreams();
|
||||
STDMETHOD(Flush)();
|
||||
|
||||
// ICompressCoder interface
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
void SetParams(BYTE reservedSize, UINT32 numInDataBlocks,
|
||||
UINT32 dictionarySizePowerOf2)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumInDataBlocks = numInDataBlocks;
|
||||
m_DictionarySizePowerOf2 = dictionarySizePowerOf2;
|
||||
if (dictionarySizePowerOf2 < 20)
|
||||
m_NumPosSlots = 30 + (dictionarySizePowerOf2 - 15) * 2;
|
||||
else if (dictionarySizePowerOf2 == 20)
|
||||
m_NumPosSlots = 42;
|
||||
else
|
||||
m_NumPosSlots = 50;
|
||||
m_NumPosLenSlots = m_NumPosSlots * kNumLenSlots;
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
31
7zip/Archive/Cab/LZXExtConst.h
Executable file
31
7zip/Archive/Cab/LZXExtConst.h
Executable file
@@ -0,0 +1,31 @@
|
||||
// Archive/Cab/LZXExtConst.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_LZXEXTCONST_H
|
||||
#define __ARCHIVE_CAB_LZXEXTCONST_H
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
const UINT32 kNumRepDistances = 3;
|
||||
|
||||
const UINT32 kNumLenSlots = 8;
|
||||
const UINT32 kMatchMinLen = 2;
|
||||
const UINT32 kNumLenSymbols = 249;
|
||||
const UINT32 kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1;
|
||||
|
||||
const BYTE kNumAlignBits = 3;
|
||||
const UINT32 kAlignTableSize = 1 << kNumAlignBits;
|
||||
|
||||
const UINT32 kNumHuffmanBits = 16;
|
||||
|
||||
const int kNumPosSlotSymbols = 50;
|
||||
const int kNumPosSlotLenSlotSymbols = kNumPosSlotSymbols * kNumLenSlots;
|
||||
|
||||
const int kMaxTableSize = 256 + kNumPosSlotLenSlotSymbols;
|
||||
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
#endif;
|
||||
124
7zip/Archive/Cab/LZXi86Converter.cpp
Executable file
124
7zip/Archive/Cab/LZXi86Converter.cpp
Executable file
@@ -0,0 +1,124 @@
|
||||
// Archive/Cab/LZXi86Converter.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "LZXi86Converter.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
Ci86TranslationOutStream::Ci86TranslationOutStream():
|
||||
m_Pos(0)
|
||||
{
|
||||
}
|
||||
|
||||
Ci86TranslationOutStream::~Ci86TranslationOutStream()
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
void Ci86TranslationOutStream::Init(ISequentialOutStream *aStream,
|
||||
bool aTranslationMode, UINT32 aTranslationSize)
|
||||
{
|
||||
m_Stream = aStream;
|
||||
m_TranslationMode = aTranslationMode;
|
||||
m_TranslationSize = aTranslationSize;
|
||||
m_ProcessedSize = 0;
|
||||
m_Pos = 0;
|
||||
}
|
||||
|
||||
void Ci86TranslationOutStream::ReleaseStream()
|
||||
{
|
||||
m_Stream.Release();
|
||||
}
|
||||
|
||||
inline INT32 Ci86TranslationOutStream::ConvertAbsoluteToOffset(INT32 aPos, INT32 anAbsoluteValue)
|
||||
{
|
||||
}
|
||||
|
||||
static const int kResidue = 6 + 4;
|
||||
|
||||
void Ci86TranslationOutStream::MakeTranslation()
|
||||
{
|
||||
if (m_Pos <= kResidue)
|
||||
return;
|
||||
UINT32 aNumBytes = m_Pos - kResidue;
|
||||
for (UINT32 i = 0; i < aNumBytes;)
|
||||
{
|
||||
if (m_Buffer[i] == 0xE8)
|
||||
{
|
||||
i++;
|
||||
INT32 anAbsoluteValue = 0;
|
||||
for(int j = 0; j < 4; j++)
|
||||
anAbsoluteValue += UINT32(m_Buffer[i + j]) << (j * 8);
|
||||
|
||||
INT32 aPos = m_ProcessedSize + i - 1;
|
||||
UINT32 anOffset;
|
||||
if (anAbsoluteValue < -aPos || anAbsoluteValue >= INT32(m_TranslationSize))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
anOffset = (anAbsoluteValue >= 0) ?
|
||||
anAbsoluteValue - aPos :
|
||||
anAbsoluteValue + m_TranslationSize;
|
||||
for(j = 0; j < 4; j++)
|
||||
{
|
||||
m_Buffer[i + j] = BYTE(anOffset & 0xFF);
|
||||
anOffset >>= 8;
|
||||
}
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP Ci86TranslationOutStream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
|
||||
{
|
||||
if (!m_TranslationMode)
|
||||
return m_Stream->Write(aData, aSize, aProcessedSize);
|
||||
|
||||
UINT32 aProcessedSizeReal = 0;
|
||||
|
||||
while (aProcessedSizeReal < aSize)
|
||||
{
|
||||
UINT32 aWriteSize = MyMin(aSize - aProcessedSizeReal, kUncompressedBlockSize - m_Pos);
|
||||
memmove(m_Buffer + m_Pos, (const BYTE *)aData + aProcessedSizeReal, aWriteSize);
|
||||
m_Pos += aWriteSize;
|
||||
aProcessedSizeReal += aWriteSize;
|
||||
if (m_Pos == kUncompressedBlockSize)
|
||||
{
|
||||
RINOK(Flush());
|
||||
}
|
||||
}
|
||||
if (aProcessedSize != NULL)
|
||||
*aProcessedSize = aProcessedSizeReal;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP Ci86TranslationOutStream::WritePart(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
|
||||
{
|
||||
return Write(aData, aSize, aProcessedSize);
|
||||
}
|
||||
|
||||
HRESULT Ci86TranslationOutStream::Flush()
|
||||
{
|
||||
if (m_Pos == 0)
|
||||
return S_OK;
|
||||
MakeTranslation();
|
||||
RINOK(m_Stream->Write(m_Buffer, m_Pos, NULL));
|
||||
m_ProcessedSize += m_Pos;
|
||||
m_Pos = 0;
|
||||
m_TranslationMode = (m_ProcessedSize < (1 << 30));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
46
7zip/Archive/Cab/LZXi86Converter.h
Executable file
46
7zip/Archive/Cab/LZXi86Converter.h
Executable file
@@ -0,0 +1,46 @@
|
||||
// Archive/Cab/LZXi86Converter.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_LZXI86CONVERTER_H
|
||||
#define __ARCHIVE_CAB_LZXI86CONVERTER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
const int kUncompressedBlockSize = 1 << 15;
|
||||
|
||||
class Ci86TranslationOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
bool m_TranslationMode;
|
||||
CMyComPtr<ISequentialOutStream> m_Stream;
|
||||
UINT32 m_ProcessedSize;
|
||||
BYTE m_Buffer[kUncompressedBlockSize];
|
||||
UINT32 m_Pos;
|
||||
UINT32 m_TranslationSize;
|
||||
|
||||
INT32 ConvertAbsoluteToOffset(INT32 aPos, INT32 anAbsoluteValue);
|
||||
void MakeTranslation();
|
||||
public:
|
||||
Ci86TranslationOutStream();
|
||||
~Ci86TranslationOutStream();
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
|
||||
STDMETHOD(WritePart)(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
|
||||
public:
|
||||
void Init(ISequentialOutStream *aStream, bool aTranslationMode, UINT32 aTranslationSize);
|
||||
HRESULT Flush();
|
||||
void ReleaseStream();
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
94
7zip/Archive/Cab/MSZipConst.h
Executable file
94
7zip/Archive/Cab/MSZipConst.h
Executable file
@@ -0,0 +1,94 @@
|
||||
// MSZipConst.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __MSZIP_CONST_H
|
||||
#define __MSZIP_CONST_H
|
||||
|
||||
#include "MSZipExtConst.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NMSZip {
|
||||
|
||||
const UINT32 kLenTableSize = 29;
|
||||
|
||||
const UINT32 kStaticDistTableSize = 32;
|
||||
const UINT32 kStaticLenTableSize = 31;
|
||||
|
||||
const UINT32 kReadTableNumber = 0x100;
|
||||
const UINT32 kMatchNumber = kReadTableNumber + 1;
|
||||
|
||||
const UINT32 kMainTableSize = kMatchNumber + kLenTableSize; //298;
|
||||
const UINT32 kStaticMainTableSize = kMatchNumber + kStaticLenTableSize; //298;
|
||||
|
||||
const UINT32 kDistTableStart = kMainTableSize;
|
||||
|
||||
const UINT32 kHeapTablesSizesSum = kMainTableSize + kDistTableSize;
|
||||
|
||||
const UINT32 kLevelTableSize = 19;
|
||||
|
||||
const UINT32 kMaxTableSize = kHeapTablesSizesSum; // test it
|
||||
const UINT32 kStaticMaxTableSize = kStaticMainTableSize + kStaticDistTableSize;
|
||||
|
||||
const UINT32 kTableDirectLevels = 16;
|
||||
const UINT32 kTableLevelRepNumber = kTableDirectLevels;
|
||||
const UINT32 kTableLevel0Number = kTableLevelRepNumber + 1;
|
||||
const UINT32 kTableLevel0Number2 = kTableLevel0Number + 1;
|
||||
|
||||
const UINT32 kLevelMask = 0xF;
|
||||
|
||||
const BYTE kLenStart[kLenTableSize] = {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255};
|
||||
const BYTE kLenDirectBits[kLenTableSize] = {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
|
||||
|
||||
|
||||
const UINT32 kDistStart[kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576};
|
||||
const BYTE kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
|
||||
|
||||
const BYTE kLevelDirectBits[kLevelTableSize] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7};
|
||||
|
||||
const BYTE kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
const UINT32 kMatchMinLen = 3;
|
||||
const UINT32 kMatchMaxLen = kNumLenCombinations + kMatchMinLen - 1; //255 + 2; test it
|
||||
|
||||
const int kFinalBlockFieldSize = 1;
|
||||
|
||||
namespace NFinalBlockField
|
||||
{
|
||||
enum
|
||||
{
|
||||
kNotFinalBlock = 0,
|
||||
kFinalBlock = 1
|
||||
};
|
||||
}
|
||||
|
||||
const int kBlockTypeFieldSize = 2;
|
||||
|
||||
namespace NBlockType
|
||||
{
|
||||
enum
|
||||
{
|
||||
kStored = 0,
|
||||
kFixedHuffman = 1,
|
||||
kDynamicHuffman = 2,
|
||||
kReserved = 3
|
||||
};
|
||||
}
|
||||
|
||||
const UINT32 kDeflateNumberOfLengthCodesFieldSize = 5;
|
||||
const UINT32 kDeflateNumberOfDistanceCodesFieldSize = 5;
|
||||
const UINT32 kDeflateNumberOfLevelCodesFieldSize = 4;
|
||||
|
||||
const UINT32 kDeflateNumberOfLitLenCodesMin = 257;
|
||||
|
||||
const UINT32 kDeflateNumberOfDistanceCodesMin = 1;
|
||||
const UINT32 kDeflateNumberOfLevelCodesMin = 4;
|
||||
|
||||
const UINT32 kDeflateLevelCodeFieldSize = 3;
|
||||
|
||||
const UINT32 kDeflateStoredBlockLengthFieldSizeSize = 16;
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
269
7zip/Archive/Cab/MSZipDecoder.cpp
Executable file
269
7zip/Archive/Cab/MSZipDecoder.cpp
Executable file
@@ -0,0 +1,269 @@
|
||||
// Archive/Cab/MSZipDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MSZipDecoder.h"
|
||||
#include "MSZipConst.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NMSZip {
|
||||
|
||||
CDecoder::CDecoder():
|
||||
m_MainDecoder(kStaticMainTableSize),
|
||||
m_DistDecoder(kStaticDistTableSize),
|
||||
m_LevelDecoder(kLevelTableSize)
|
||||
{
|
||||
m_OutWindowStream.Create(kHistorySize);
|
||||
}
|
||||
|
||||
HRESULT CDecoder::Flush()
|
||||
{
|
||||
return m_OutWindowStream.Flush();
|
||||
}
|
||||
|
||||
/*
|
||||
void CDecoder::ReleaseStreams()
|
||||
{
|
||||
m_OutWindowStream.ReleaseStream();
|
||||
m_InBitStream.ReleaseStream();
|
||||
}
|
||||
*/
|
||||
|
||||
void CDecoder::DeCodeLevelTable(BYTE *newLevels, int numLevels)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < numLevels)
|
||||
{
|
||||
UINT32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (number < kTableDirectLevels)
|
||||
newLevels[i++] = BYTE(number);
|
||||
else
|
||||
{
|
||||
if (number == kTableLevelRepNumber)
|
||||
{
|
||||
int t = m_InBitStream.ReadBits(2) + 3;
|
||||
for (int reps = t; reps > 0 && i < numLevels ; reps--, i++)
|
||||
newLevels[i] = newLevels[i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
int num;
|
||||
if (number == kTableLevel0Number)
|
||||
num = m_InBitStream.ReadBits(3) + 3;
|
||||
else
|
||||
num = m_InBitStream.ReadBits(7) + 11;
|
||||
for (;num > 0 && i < numLevels; num--)
|
||||
newLevels[i++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDecoder::ReadTables(void)
|
||||
{
|
||||
if(m_FinalBlock) // test it
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
|
||||
m_FinalBlock = (m_InBitStream.ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
|
||||
|
||||
int blockType = m_InBitStream.ReadBits(kBlockTypeFieldSize);
|
||||
|
||||
switch(blockType)
|
||||
{
|
||||
case NBlockType::kStored:
|
||||
{
|
||||
m_StoredMode = true;
|
||||
UINT32 currentBitPosition = m_InBitStream.GetBitPosition();
|
||||
UINT32 numBitsForAlign = currentBitPosition > 0 ? (8 - currentBitPosition): 0;
|
||||
if (numBitsForAlign > 0)
|
||||
m_InBitStream.ReadBits(numBitsForAlign);
|
||||
m_StoredBlockSize = m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize);
|
||||
WORD onesComplementReverse = ~WORD(m_InBitStream.ReadBits(kDeflateStoredBlockLengthFieldSizeSize));
|
||||
if (m_StoredBlockSize != onesComplementReverse)
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
break;
|
||||
}
|
||||
case NBlockType::kFixedHuffman:
|
||||
case NBlockType::kDynamicHuffman:
|
||||
{
|
||||
m_StoredMode = false;
|
||||
BYTE litLenLevels[kStaticMainTableSize];
|
||||
BYTE distLevels[kStaticDistTableSize];
|
||||
if (blockType == NBlockType::kFixedHuffman)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Leteral / length levels
|
||||
for (i = 0; i < 144; i++)
|
||||
litLenLevels[i] = 8;
|
||||
for (; i < 256; i++)
|
||||
litLenLevels[i] = 9;
|
||||
for (; i < 280; i++)
|
||||
litLenLevels[i] = 7;
|
||||
for (; i < 288; i++) /* make a complete, but wrong code set */
|
||||
litLenLevels[i] = 8;
|
||||
|
||||
// Distance levels
|
||||
for (i = 0; i < kStaticDistTableSize; i++) // test it: infozip only use kDistTableSize
|
||||
distLevels[i] = 5;
|
||||
}
|
||||
else // in case when (blockType == kDeflateBlockTypeFixedHuffman)
|
||||
{
|
||||
int numLitLenLevels = m_InBitStream.ReadBits(kDeflateNumberOfLengthCodesFieldSize) +
|
||||
kDeflateNumberOfLitLenCodesMin;
|
||||
int numDistLevels = m_InBitStream.ReadBits(kDeflateNumberOfDistanceCodesFieldSize) +
|
||||
kDeflateNumberOfDistanceCodesMin;
|
||||
int numLevelCodes = m_InBitStream.ReadBits(kDeflateNumberOfLevelCodesFieldSize) +
|
||||
kDeflateNumberOfLevelCodesMin;
|
||||
|
||||
int numLevels;
|
||||
numLevels = kHeapTablesSizesSum;
|
||||
|
||||
BYTE levelLevels[kLevelTableSize];
|
||||
int i;
|
||||
for (i = 0; i < kLevelTableSize; i++)
|
||||
{
|
||||
int position = kCodeLengthAlphabetOrder[i];
|
||||
if(i < numLevelCodes)
|
||||
levelLevels[position] = BYTE(m_InBitStream.ReadBits(kDeflateLevelCodeFieldSize));
|
||||
else
|
||||
levelLevels[position] = 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
m_LevelDecoder.SetCodeLengths(levelLevels);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
}
|
||||
|
||||
BYTE tmpLevels[kStaticMaxTableSize];
|
||||
DeCodeLevelTable(tmpLevels, numLitLenLevels + numDistLevels);
|
||||
|
||||
memmove(litLenLevels, tmpLevels, numLitLenLevels);
|
||||
memset(litLenLevels + numLitLenLevels, 0,
|
||||
kStaticMainTableSize - numLitLenLevels);
|
||||
|
||||
memmove(distLevels, tmpLevels + numLitLenLevels, numDistLevels);
|
||||
memset(distLevels + numDistLevels, 0, kStaticDistTableSize - numDistLevels);
|
||||
}
|
||||
try
|
||||
{
|
||||
m_MainDecoder.SetCodeLengths(litLenLevels);
|
||||
m_DistDecoder.SetCodeLengths(distLevels);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
}
|
||||
}
|
||||
|
||||
class CCoderReleaser
|
||||
{
|
||||
CDecoder *m_Coder;
|
||||
public:
|
||||
CCoderReleaser(CDecoder *aCoder): m_Coder(aCoder) {}
|
||||
~CCoderReleaser()
|
||||
{
|
||||
m_Coder->Flush();
|
||||
// m_Coder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (outSize == NULL)
|
||||
return E_INVALIDARG;
|
||||
UINT64 size = *outSize;
|
||||
|
||||
m_OutWindowStream.Init(outStream, false);
|
||||
m_InBitStream.InitMain(inStream, m_ReservedSize, m_NumInDataBlocks);
|
||||
CCoderReleaser coderReleaser(this);
|
||||
|
||||
UINT64 nowPos = 0;
|
||||
while(nowPos < size)
|
||||
{
|
||||
if (progress != NULL)
|
||||
{
|
||||
UINT64 packSize = m_InBitStream.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
|
||||
}
|
||||
UINT32 uncompressedCFDataBlockSize;
|
||||
bool dataAreCorrect;
|
||||
RINOK(m_InBitStream.ReadBlock(uncompressedCFDataBlockSize, dataAreCorrect));
|
||||
if (!dataAreCorrect)
|
||||
{
|
||||
throw "Data Error";
|
||||
}
|
||||
m_InBitStream.Init();
|
||||
if (m_InBitStream.ReadBits(8) != 0x43)
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
if (m_InBitStream.ReadBits(8) != 0x4B)
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
UINT32 uncompressedCFDataCurrentValue = 0;
|
||||
m_FinalBlock = false;
|
||||
while (uncompressedCFDataCurrentValue < uncompressedCFDataBlockSize)
|
||||
{
|
||||
ReadTables();
|
||||
if(m_StoredMode)
|
||||
{
|
||||
for (UINT32 i = 0; i < m_StoredBlockSize; i++)
|
||||
m_OutWindowStream.PutOneByte(BYTE(m_InBitStream.ReadBits(8)));
|
||||
nowPos += m_StoredBlockSize;
|
||||
uncompressedCFDataCurrentValue += m_StoredBlockSize;
|
||||
continue;
|
||||
}
|
||||
while(true)
|
||||
{
|
||||
UINT32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
|
||||
|
||||
if (number < 256)
|
||||
{
|
||||
m_OutWindowStream.PutOneByte(BYTE(number));
|
||||
nowPos++;
|
||||
uncompressedCFDataCurrentValue++;
|
||||
continue;
|
||||
}
|
||||
else if (number >= kMatchNumber)
|
||||
{
|
||||
number -= kMatchNumber;
|
||||
UINT32 length = UINT32(kLenStart[number]) + kMatchMinLen;
|
||||
UINT32 numBits;
|
||||
if ((numBits = kLenDirectBits[number]) > 0)
|
||||
length += m_InBitStream.ReadBits(numBits);
|
||||
|
||||
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
|
||||
UINT32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
|
||||
/*
|
||||
if (distance >= nowPos)
|
||||
throw "data error";
|
||||
*/
|
||||
m_OutWindowStream.CopyBackBlock(distance, length);
|
||||
nowPos += length;
|
||||
uncompressedCFDataCurrentValue += length;
|
||||
}
|
||||
else if (number == kReadTableNumber)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}}
|
||||
88
7zip/Archive/Cab/MSZipDecoder.h
Executable file
88
7zip/Archive/Cab/MSZipDecoder.h
Executable file
@@ -0,0 +1,88 @@
|
||||
// Archive/Cab/MSZipDecoder.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __ARCHIVE_CAB_DECODER_H
|
||||
#define __ARCHIVE_CAB_DECODER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../ICoder.h"
|
||||
#include "../../Common/LSBFDecoder.h"
|
||||
#include "../../Compress/Huffman/HuffmanDecoder.h"
|
||||
#include "../../Compress/LZ/LZOutWindow.h"
|
||||
|
||||
#include "CabInBuffer.h"
|
||||
#include "MSZipExtConst.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NMSZip {
|
||||
|
||||
class CDecoderException
|
||||
{
|
||||
public:
|
||||
enum ECauseType
|
||||
{
|
||||
kData
|
||||
} m_Cause;
|
||||
CDecoderException(ECauseType aCause): m_Cause(aCause) {}
|
||||
};
|
||||
|
||||
class CMSZipBitDecoder: public NStream::NLSBF::CDecoder<NCab::CInBuffer>
|
||||
{
|
||||
public:
|
||||
void InitMain(ISequentialInStream *aStream, BYTE aReservedSize, UINT32 aNumBlocks)
|
||||
{
|
||||
m_Stream.Init(aStream, aReservedSize, aNumBlocks);
|
||||
Init();
|
||||
}
|
||||
HRESULT ReadBlock(UINT32 &anUncompressedSize, bool &aDataAreCorrect)
|
||||
{
|
||||
return m_Stream.ReadBlock(anUncompressedSize, aDataAreCorrect);
|
||||
}
|
||||
};
|
||||
|
||||
typedef NCompress::NHuffman::CDecoder<kNumHuffmanBits> CHuffmanDecoder;
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
CMSZipBitDecoder m_InBitStream;
|
||||
CHuffmanDecoder m_MainDecoder;
|
||||
CHuffmanDecoder m_DistDecoder;
|
||||
CHuffmanDecoder m_LevelDecoder; // table for decoding other tables;
|
||||
|
||||
bool m_FinalBlock;
|
||||
bool m_StoredMode;
|
||||
UINT32 m_StoredBlockSize;
|
||||
|
||||
BYTE m_ReservedSize;
|
||||
UINT32 m_NumInDataBlocks;
|
||||
|
||||
void DeCodeLevelTable(BYTE *newLevels, int numLevels);
|
||||
void ReadTables();
|
||||
public:
|
||||
CDecoder();
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
HRESULT Flush();
|
||||
// void ReleaseStreams();
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UINT64 *inSize, const UINT64 *outSize,
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
void SetParams(BYTE aReservedSize, UINT32 aNumInDataBlocks)
|
||||
{
|
||||
m_ReservedSize = aReservedSize;
|
||||
m_NumInDataBlocks = aNumInDataBlocks;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
22
7zip/Archive/Cab/MSZipExtConst.h
Executable file
22
7zip/Archive/Cab/MSZipExtConst.h
Executable file
@@ -0,0 +1,22 @@
|
||||
// DeflateExtConst.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __DEFLATEEXTCONST_H
|
||||
#define __DEFLATEEXTCONST_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NMSZip {
|
||||
|
||||
const UINT32 kDistTableSize = 30;
|
||||
const UINT32 kHistorySize = 0x8000;
|
||||
const UINT32 kNumLenCombinations = 256;
|
||||
|
||||
const UINT32 kNumHuffmanBits = 15;
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
3
7zip/Archive/Cab/StdAfx.cpp
Executable file
3
7zip/Archive/Cab/StdAfx.cpp
Executable file
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "stdafx.h"
|
||||
9
7zip/Archive/Cab/StdAfx.h
Executable file
9
7zip/Archive/Cab/StdAfx.h
Executable file
@@ -0,0 +1,9 @@
|
||||
// stdafx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
|
||||
#endif
|
||||
BIN
7zip/Archive/Cab/cab.ico
Executable file
BIN
7zip/Archive/Cab/cab.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
16
7zip/Archive/Cab/resource.h
Executable file
16
7zip/Archive/Cab/resource.h
Executable file
@@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by resource.rc
|
||||
//
|
||||
#define IDI_ICON1 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
130
7zip/Archive/Cab/resource.rc
Executable file
130
7zip/Archive/Cab/resource.rc
Executable file
@@ -0,0 +1,130 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Russian resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
#pragma code_page(1251)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Russian resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,12,0,0
|
||||
PRODUCTVERSION 3,12,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "\0"
|
||||
VALUE "CompanyName", "Igor Pavlov \0"
|
||||
VALUE "FileDescription", "Cab Plugin for 7-Zip\0"
|
||||
VALUE "FileVersion", "3, 12, 0, 0\0"
|
||||
VALUE "InternalName", "cab\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "cab.dll\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "7-Zip\0"
|
||||
VALUE "ProductVersion", "3, 12, 0, 0\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "cab.ico"
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
Reference in New Issue
Block a user