mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-10 06:07:07 -06:00
4.27 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
31e7b924e8
commit
d66cf2fcf3
@@ -496,6 +496,14 @@ SOURCE=..\..\Common\StreamObjects.cpp
|
||||
|
||||
SOURCE=..\..\Common\StreamObjects.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Windows"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Decode.cpp
|
||||
// 7zDecode.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -136,10 +136,10 @@ static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
|
||||
|
||||
CDecoder::CDecoder(bool multiThread)
|
||||
{
|
||||
_multiThread = true;
|
||||
#ifdef _ST_MODE
|
||||
_multiThread = multiThread;
|
||||
#ifndef _ST_MODE
|
||||
multiThread = true;
|
||||
#endif
|
||||
_multiThread = multiThread;
|
||||
_bindInfoExPrevIsDefinded = false;
|
||||
#ifndef EXCLUDE_COM
|
||||
LoadMethodMap();
|
||||
|
||||
@@ -142,7 +142,13 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
extractCallback->SetTotal(importantTotalUnPacked);
|
||||
|
||||
CDecoder decoder(true);
|
||||
CDecoder decoder(
|
||||
#ifdef _ST_MODE
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
// CDecoder1 decoder;
|
||||
|
||||
UInt64 currentImportantTotalUnPacked = 0;
|
||||
|
||||
@@ -79,7 +79,7 @@ HRESULT CFolderInStream::CloseStream()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
|
||||
@@ -87,7 +87,7 @@ STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processe
|
||||
if (_fileIsOpen)
|
||||
{
|
||||
UInt32 localProcessedSize;
|
||||
RINOK(_inStreamWithHash->ReadPart(
|
||||
RINOK(_inStreamWithHash->Read(
|
||||
((Byte *)data) + realProcessedSize, size, &localProcessedSize));
|
||||
if (localProcessedSize == 0)
|
||||
{
|
||||
@@ -109,24 +109,6 @@ STDMETHODIMP CFolderInStream::ReadPart(void *data, UInt32 size, UInt32 *processe
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize = 0;
|
||||
while (size > 0)
|
||||
{
|
||||
UInt32 localProcessedSize;
|
||||
RINOK(ReadPart(((Byte *)data) + realProcessedSize, size, &localProcessedSize));
|
||||
if (localProcessedSize == 0)
|
||||
break;
|
||||
size -= localProcessedSize;
|
||||
realProcessedSize += localProcessedSize;
|
||||
}
|
||||
if (processedSize != 0)
|
||||
*processedSize = realProcessedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
*value = 0;
|
||||
|
||||
@@ -26,7 +26,6 @@ public:
|
||||
CFolderInStream();
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
private:
|
||||
|
||||
@@ -91,7 +91,8 @@ STDMETHODIMP CFolderOutStream::Write(const void *data,
|
||||
UInt64(size - realProcessedSize));
|
||||
|
||||
UInt32 processedSizeLocal;
|
||||
RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize, numBytesToWrite, &processedSizeLocal));
|
||||
RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
|
||||
numBytesToWrite, &processedSizeLocal));
|
||||
|
||||
_filePos += processedSizeLocal;
|
||||
realProcessedSize += processedSizeLocal;
|
||||
@@ -130,12 +131,6 @@ STDMETHODIMP CFolderOutStream::Write(const void *data,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFolderOutStream::WritePart(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
|
||||
{
|
||||
while(_currentIndex < _extractStatuses->Size())
|
||||
|
||||
@@ -22,7 +22,6 @@ public:
|
||||
CFolderOutStream();
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
|
||||
COutStreamWithCRC *_outStreamWithHashSpec;
|
||||
|
||||
@@ -50,9 +50,9 @@ struct COneMethodInfo
|
||||
};
|
||||
#endif
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110050000}
|
||||
// {23170F69-40C1-278A-1000-000110070000}
|
||||
DEFINE_GUID(CLSID_CFormat7z,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
|
||||
|
||||
class CHandler:
|
||||
public IInArchive,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "7zMethods.h"
|
||||
#include "7zDecode.h"
|
||||
#include "../../Common/StreamObjects.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../../Common/CRC.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -69,7 +70,7 @@ HRESULT CInArchive::ReadDirect(IInStream *stream, void *data, UInt32 size,
|
||||
UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = stream->Read(data, size, &realProcessedSize);
|
||||
HRESULT result = ReadStream(stream, data, size, &realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
_position += realProcessedSize;
|
||||
@@ -850,7 +851,13 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(UInt64 baseOffset,
|
||||
// database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
|
||||
|
||||
CNum packIndex = 0;
|
||||
CDecoder decoder(false);
|
||||
CDecoder decoder(
|
||||
#ifdef _ST_MODE
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
UInt64 dataStartPos = baseOffset + dataOffset;
|
||||
for(int i = 0; i < folders.Size(); i++)
|
||||
{
|
||||
|
||||
@@ -11,10 +11,10 @@ static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t
|
||||
{
|
||||
while (size > 0)
|
||||
{
|
||||
UInt32 curSize = (UInt32)(MyMin(size, (size_t)0xFFFFFFFF));
|
||||
UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
|
||||
UInt32 processedSize;
|
||||
RINOK(stream->WritePart(data, curSize, &processedSize));
|
||||
if(processedSize == 0 || processedSize > curSize)
|
||||
RINOK(stream->Write(data, curSize, &processedSize));
|
||||
if(processedSize == 0)
|
||||
return E_FAIL;
|
||||
data = (const void *)((const Byte *)data + processedSize);
|
||||
size -= processedSize;
|
||||
@@ -111,7 +111,10 @@ HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
|
||||
{
|
||||
SeqStream.QueryInterface(IID_IOutStream, &Stream);
|
||||
if (!Stream)
|
||||
endMarker = true;
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
// endMarker = true;
|
||||
}
|
||||
}
|
||||
#ifdef _7Z_VOL
|
||||
if (endMarker)
|
||||
|
||||
@@ -14,16 +14,6 @@ STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamSizeCount2::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
if (processedSize != 0)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(
|
||||
UInt64 subStream, UInt64 *value)
|
||||
{
|
||||
|
||||
@@ -28,7 +28,6 @@ public:
|
||||
MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
|
||||
};
|
||||
|
||||
@@ -89,11 +89,13 @@ UString CUpdateItem::GetExtension() const
|
||||
return Name.Mid(GetExtensionPos());
|
||||
}
|
||||
|
||||
/*
|
||||
struct CFolderRef
|
||||
{
|
||||
const CArchiveDatabaseEx *Database;
|
||||
int FolderIndex;
|
||||
};
|
||||
*/
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
@@ -159,31 +161,31 @@ static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
|
||||
return MyStringCollateNoCase(f1.Name, f2.Name);
|
||||
}
|
||||
|
||||
static int __cdecl CompareFolderRefs(const void *p1, const void *p2)
|
||||
static int CompareFolderRefs(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CFolderRef &a1 = *((const CFolderRef *)p1);
|
||||
const CFolderRef &a2 = *((const CFolderRef *)p2);
|
||||
const CArchiveDatabaseEx &d1 = *a1.Database;
|
||||
const CArchiveDatabaseEx &d2 = *a2.Database;
|
||||
int i1 = *p1;
|
||||
int i2 = *p2;
|
||||
const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
|
||||
RINOZ(CompareFolders(
|
||||
d1.Folders[a1.FolderIndex],
|
||||
d2.Folders[a2.FolderIndex]));
|
||||
db.Folders[i1],
|
||||
db.Folders[i2]));
|
||||
RINOZ(MyCompare(
|
||||
d1.NumUnPackStreamsVector[a1.FolderIndex],
|
||||
d2.NumUnPackStreamsVector[a2.FolderIndex]));
|
||||
if (d1.NumUnPackStreamsVector[a1.FolderIndex] == 0)
|
||||
db.NumUnPackStreamsVector[i1],
|
||||
db.NumUnPackStreamsVector[i2]));
|
||||
if (db.NumUnPackStreamsVector[i1] == 0)
|
||||
return 0;
|
||||
return CompareFiles(
|
||||
d1.Files[d1.FolderStartFileIndex[a1.FolderIndex]],
|
||||
d2.Files[d2.FolderStartFileIndex[a2.FolderIndex]]);
|
||||
db.Files[db.FolderStartFileIndex[i1]],
|
||||
db.Files[db.FolderStartFileIndex[i2]]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
static int __cdecl CompareEmptyItems(const void *p1, const void *p2)
|
||||
static int CompareEmptyItems(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CUpdateItem &u1 = **((CUpdateItem **)p1);
|
||||
const CUpdateItem &u2 = **((CUpdateItem **)p2);
|
||||
const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
|
||||
const CUpdateItem &u1 = updateItems[*p1];
|
||||
const CUpdateItem &u2 = updateItems[*p2];
|
||||
if (u1.IsDirectory != u2.IsDirectory)
|
||||
{
|
||||
if (u1.IsDirectory)
|
||||
@@ -234,10 +236,10 @@ struct CRefItem
|
||||
}
|
||||
};
|
||||
|
||||
static int __cdecl CompareUpdateItems(const void *p1, const void *p2)
|
||||
static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
|
||||
{
|
||||
const CRefItem &a1 = *((CRefItem *)p1);
|
||||
const CRefItem &a2 = *((CRefItem *)p2);
|
||||
const CRefItem &a1 = *p1;
|
||||
const CRefItem &a2 = *p2;
|
||||
const CUpdateItem &u1 = *a1.UpdateItem;
|
||||
const CUpdateItem &u2 = *a2.UpdateItem;
|
||||
int n;
|
||||
@@ -455,7 +457,7 @@ static void FromUpdateItemToFileItem(const CUpdateItem &updateItem,
|
||||
static HRESULT Update2(
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *database,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options)
|
||||
@@ -496,38 +498,32 @@ static HRESULT Update2(
|
||||
fileIndexToUpdateIndexMap[index] = i;
|
||||
}
|
||||
|
||||
CRecordVector<CFolderRef> folderRefs;
|
||||
CRecordVector<int> folderRefs;
|
||||
if (database != 0)
|
||||
{
|
||||
for(i = 0; i < database->Folders.Size(); i++)
|
||||
{
|
||||
CNum indexInFolder = 0;
|
||||
CNum numCopyItems = 0;
|
||||
CNum numUnPackStreams = database->NumUnPackStreamsVector[i];
|
||||
for (CNum fileIndex = database->FolderStartFileIndex[i];
|
||||
indexInFolder < numUnPackStreams; fileIndex++)
|
||||
for(i = 0; i < database->Folders.Size(); i++)
|
||||
{
|
||||
if (database->Files[fileIndex].HasStream)
|
||||
CNum indexInFolder = 0;
|
||||
CNum numCopyItems = 0;
|
||||
CNum numUnPackStreams = database->NumUnPackStreamsVector[i];
|
||||
for (CNum fileIndex = database->FolderStartFileIndex[i];
|
||||
indexInFolder < numUnPackStreams; fileIndex++)
|
||||
{
|
||||
indexInFolder++;
|
||||
int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
|
||||
if (updateIndex >= 0)
|
||||
if (!updateItems[updateIndex].NewData)
|
||||
numCopyItems++;
|
||||
if (database->Files[fileIndex].HasStream)
|
||||
{
|
||||
indexInFolder++;
|
||||
int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
|
||||
if (updateIndex >= 0)
|
||||
if (!updateItems[updateIndex].NewData)
|
||||
numCopyItems++;
|
||||
}
|
||||
}
|
||||
if (numCopyItems != numUnPackStreams && numCopyItems != 0)
|
||||
return E_NOTIMPL; // It needs repacking !!!
|
||||
if (numCopyItems > 0)
|
||||
folderRefs.Add(i);
|
||||
}
|
||||
if (numCopyItems != numUnPackStreams && numCopyItems != 0)
|
||||
return E_NOTIMPL; // It needs repacking !!!
|
||||
if (numCopyItems > 0)
|
||||
{
|
||||
CFolderRef folderRef;
|
||||
folderRef.Database = database;
|
||||
folderRef.FolderIndex = i;
|
||||
folderRefs.Add(folderRef);
|
||||
}
|
||||
}
|
||||
qsort(&folderRefs.Front(), folderRefs.Size(), sizeof(folderRefs[0]),
|
||||
CompareFolderRefs);
|
||||
folderRefs.Sort(CompareFolderRefs, (void *)database);
|
||||
}
|
||||
|
||||
CArchiveDatabase newDatabase;
|
||||
@@ -535,7 +531,7 @@ static HRESULT Update2(
|
||||
/////////////////////////////////////////
|
||||
// Write Empty Files & Folders
|
||||
|
||||
CRecordVector<const CUpdateItem *> emptyRefs;
|
||||
CRecordVector<int> emptyRefs;
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[i];
|
||||
@@ -548,13 +544,12 @@ static HRESULT Update2(
|
||||
if (updateItem.IndexInArchive != -1)
|
||||
if (database->Files[updateItem.IndexInArchive].HasStream)
|
||||
continue;
|
||||
emptyRefs.Add(&updateItem);
|
||||
emptyRefs.Add(i);
|
||||
}
|
||||
qsort(&emptyRefs.Front(), emptyRefs.Size(), sizeof(emptyRefs[0]),
|
||||
CompareEmptyItems);
|
||||
emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
|
||||
for(i = 0; i < emptyRefs.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = *emptyRefs[i];
|
||||
const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
|
||||
CFileItem file;
|
||||
if (updateItem.NewProperties)
|
||||
FromUpdateItemToFileItem(updateItem, file);
|
||||
@@ -566,11 +561,11 @@ static HRESULT Update2(
|
||||
////////////////////////////
|
||||
|
||||
COutArchive archive;
|
||||
archive.Create(seqOutStream, false);
|
||||
RINOK(archive.Create(seqOutStream, false));
|
||||
RINOK(archive.SkeepPrefixArchiveHeader());
|
||||
UInt64 complexity = 0;
|
||||
for(i = 0; i < folderRefs.Size(); i++)
|
||||
complexity += database->GetFolderFullPackSize(folderRefs[i].FolderIndex);
|
||||
complexity += database->GetFolderFullPackSize(folderRefs[i]);
|
||||
for(i = 0; i < updateItems.Size(); i++)
|
||||
{
|
||||
const CUpdateItem &updateItem = updateItems[i];
|
||||
@@ -586,7 +581,7 @@ static HRESULT Update2(
|
||||
|
||||
for(i = 0; i < folderRefs.Size(); i++)
|
||||
{
|
||||
int folderIndex = folderRefs[i].FolderIndex;
|
||||
int folderIndex = folderRefs[i];
|
||||
|
||||
RINOK(WriteRange(inStream, archive.SeqStream,
|
||||
database->GetFolderStreamPos(folderIndex, 0),
|
||||
@@ -652,7 +647,7 @@ static HRESULT Update2(
|
||||
for (i = 0; i < numFiles; i++)
|
||||
refItems.Add(CRefItem(group.Indices[i],
|
||||
updateItems[group.Indices[i]], numSolidFiles > 1));
|
||||
qsort(&refItems.Front(), refItems.Size(), sizeof(refItems[0]), CompareUpdateItems);
|
||||
refItems.Sort(CompareUpdateItems, 0);
|
||||
|
||||
CRecordVector<UInt32> indices;
|
||||
indices.Reserve(numFiles);
|
||||
@@ -862,7 +857,7 @@ HRESULT UpdateVolume(
|
||||
RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream));
|
||||
|
||||
COutArchive archive;
|
||||
archive.Create(volumeStream, true);
|
||||
RINOK(archive.Create(volumeStream, true));
|
||||
RINOK(archive.SkeepPrefixArchiveHeader());
|
||||
|
||||
CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC;
|
||||
@@ -914,7 +909,6 @@ public:
|
||||
|
||||
HRESULT Flush();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
HRESULT COutVolumeStream::Flush()
|
||||
@@ -943,7 +937,7 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc
|
||||
RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream));
|
||||
_volIndex++;
|
||||
_curPos = 0;
|
||||
_archive.Create(_volumeStream, true);
|
||||
RINOK(_archive.Create(_volumeStream, true));
|
||||
RINOK(_archive.SkeepPrefixArchiveHeader());
|
||||
_crc.Init();
|
||||
continue;
|
||||
@@ -959,7 +953,7 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc
|
||||
if(processedSize != NULL)
|
||||
*processedSize += realProcessed;
|
||||
_curPos += realProcessed;
|
||||
if (realProcessed != curSize)
|
||||
if (realProcessed != curSize && realProcessed == 0)
|
||||
return E_FAIL;
|
||||
if (_curPos == pureSize)
|
||||
{
|
||||
@@ -969,16 +963,12 @@ STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *proc
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutVolumeStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT Update(
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *database,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options)
|
||||
|
||||
@@ -60,7 +60,7 @@ struct CUpdateOptions
|
||||
HRESULT Update(
|
||||
IInStream *inStream,
|
||||
const CArchiveDatabaseEx *database,
|
||||
CObjectVector<CUpdateItem> &updateItems,
|
||||
const CObjectVector<CUpdateItem> &updateItems,
|
||||
ISequentialOutStream *seqOutStream,
|
||||
IArchiveUpdateCallback *updateCallback,
|
||||
const CUpdateOptions &options);
|
||||
|
||||
@@ -48,6 +48,7 @@ WIN_OBJS = \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamBinder.obj \
|
||||
$O\StreamObjects.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CodecsPath.obj \
|
||||
|
||||
50
7zip/Archive/7z_C/makefile.gcc
Executable file
50
7zip/Archive/7z_C/makefile.gcc
Executable file
@@ -0,0 +1,50 @@
|
||||
PROG = 7zDec
|
||||
CXX = g++
|
||||
LIB =
|
||||
RM = rm -f
|
||||
CFLAGS = -c -O2 -Wall
|
||||
|
||||
OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
||||
|
||||
7zAlloc.o: 7zAlloc.c
|
||||
$(CXX) $(CFLAGS) 7zAlloc.c
|
||||
|
||||
7zBuffer.o: 7zBuffer.c
|
||||
$(CXX) $(CFLAGS) 7zBuffer.c
|
||||
|
||||
7zCrc.o: 7zCrc.c
|
||||
$(CXX) $(CFLAGS) 7zCrc.c
|
||||
|
||||
7zDecode.o: 7zDecode.c
|
||||
$(CXX) $(CFLAGS) 7zDecode.c
|
||||
|
||||
7zExtract.o: 7zExtract.c
|
||||
$(CXX) $(CFLAGS) 7zExtract.c
|
||||
|
||||
7zHeader.o: 7zHeader.c
|
||||
$(CXX) $(CFLAGS) 7zHeader.c
|
||||
|
||||
7zIn.o: 7zIn.c
|
||||
$(CXX) $(CFLAGS) 7zIn.c
|
||||
|
||||
7zItem.o: 7zItem.c
|
||||
$(CXX) $(CFLAGS) 7zItem.c
|
||||
|
||||
7zMain.o: 7zMain.c
|
||||
$(CXX) $(CFLAGS) 7zMain.c
|
||||
|
||||
7zMethodID.o: 7zMethodID.c
|
||||
$(CXX) $(CFLAGS) 7zMethodID.c
|
||||
|
||||
LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c
|
||||
$(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c
|
||||
|
||||
|
||||
clean:
|
||||
-$(RM) $(PROG) $(OBJS)
|
||||
|
||||
@@ -213,19 +213,19 @@ SOURCE=.\ArjItem.h
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Arj\Decoder1.cpp
|
||||
SOURCE=..\..\Compress\Arj\ArjDecoder1.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Arj\Decoder1.h
|
||||
SOURCE=..\..\Compress\Arj\ArjDecoder1.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Arj\Decoder2.cpp
|
||||
SOURCE=..\..\Compress\Arj\ArjDecoder2.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Arj\Decoder2.h
|
||||
SOURCE=..\..\Compress\Arj\ArjDecoder2.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "LZ"
|
||||
@@ -278,12 +278,28 @@ SOURCE=..\..\Common\MSBFDecoder.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
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
#include "../../Compress/Arj/Decoder1.h"
|
||||
#include "../../Compress/Arj/Decoder2.h"
|
||||
#include "../../Compress/Arj/ArjDecoder1.h"
|
||||
#include "../../Compress/Arj/ArjDecoder2.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
#include "../Common/OutStreamWithCRC.h"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/CRC.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "ArjIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -14,7 +16,7 @@ namespace NArj {
|
||||
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->Read(data, size, &realProcessedSize);
|
||||
HRESULT result = ReadStream(_stream, data, size, &realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
IncreasePositionValue(realProcessedSize);
|
||||
@@ -162,7 +164,7 @@ bool CInArchive::ReadBlock()
|
||||
{
|
||||
_blockPos = 0;
|
||||
_blockSize = SafeReadUInt16();
|
||||
if (_blockSize == 0)
|
||||
if (_blockSize == 0 || _blockSize > kMaxBlockSize)
|
||||
return false;
|
||||
SafeReadBytes(_block, _blockSize);
|
||||
UInt32 crcFromFile = SafeReadUInt32();
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "../../ICoder.h"
|
||||
#include "ArjHandler.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-0001100A0000}
|
||||
// {23170F69-40C1-278A-1000-000110040000}
|
||||
DEFINE_GUID(CLSID_CArjHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0A, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
|
||||
@@ -22,15 +22,17 @@ WIN_OBJS = \
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\InBuffer.obj \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
$O\OutStreamWithCRC.obj \
|
||||
|
||||
COMPRESS_ARJ_OBJS = \
|
||||
$O\Decoder1.obj \
|
||||
$O\Decoder2.obj \
|
||||
$O\ArjDecoder1.obj \
|
||||
$O\ArjDecoder2.obj \
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
|
||||
@@ -256,6 +256,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
// #include "Interface/EnumStatProp.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "Windows/Defs.h"
|
||||
@@ -111,7 +111,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||
const int kSignatureSize = 3;
|
||||
Byte buffer[kSignatureSize];
|
||||
UInt32 processedSize;
|
||||
RINOK(stream->Read(buffer, kSignatureSize, &processedSize));
|
||||
RINOK(ReadStream(stream, buffer, kSignatureSize, &processedSize));
|
||||
if (processedSize != kSignatureSize)
|
||||
return S_FALSE;
|
||||
if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
|
||||
@@ -221,7 +221,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
const int kSignatureSize = 3;
|
||||
Byte buffer[kSignatureSize];
|
||||
UInt32 processedSize;
|
||||
RINOK(_stream->Read(buffer, kSignatureSize, &processedSize));
|
||||
RINOK(ReadStream(_stream, buffer, kSignatureSize, &processedSize));
|
||||
if (processedSize < kSignatureSize)
|
||||
{
|
||||
if (firstItem)
|
||||
|
||||
@@ -16,9 +16,9 @@ DEFINE_GUID(CLSID_CCompressBZip2Encoder,
|
||||
DEFINE_GUID(CLSID_CCompressBZip2Decoder,
|
||||
0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110070000}
|
||||
// {23170F69-40C1-278A-1000-000110020000}
|
||||
DEFINE_GUID(CLSID_CBZip2Handler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00);
|
||||
|
||||
HINSTANCE g_hInstance;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ WIN_OBJS = \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CodecsPath.obj \
|
||||
|
||||
@@ -43,7 +43,7 @@ RSC=rc.exe
|
||||
# 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 CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAs /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"
|
||||
@@ -70,7 +70,7 @@ LINK32=link.exe
|
||||
# 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 CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAcs /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"
|
||||
@@ -190,11 +190,11 @@ SOURCE=..\..\..\Windows\PropVariant.h
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabCopyDecoder.cpp
|
||||
SOURCE=.\CabBlockInStream.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\CabCopyDecoder.h
|
||||
SOURCE=.\CabBlockInStream.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -222,60 +222,8 @@ 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"
|
||||
|
||||
@@ -298,6 +246,10 @@ SOURCE=..\..\Common\LSBFDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\MSBFDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\OutBuffer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -306,11 +258,11 @@ SOURCE=..\..\Common\OutBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Compress"
|
||||
@@ -328,6 +280,112 @@ SOURCE=..\..\Compress\LZ\LZOutWindow.cpp
|
||||
SOURCE=..\..\Compress\LZ\LZOutWindow.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Lzx"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp
|
||||
|
||||
!IF "$(CFG)" == "Cab - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx86Converter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp
|
||||
|
||||
!IF "$(CFG)" == "Cab - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\LzxDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Deflate"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Deflate\DeflateConst.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Deflate\DeflateDecoder.cpp
|
||||
|
||||
!IF "$(CFG)" == "Cab - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Deflate\DeflateDecoder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Deflate\DeflateExtConst.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Copy"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Copy\CopyCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Copy\CopyCoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Quantum"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Quantum\QuantumDecoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Quantum\QuantumDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Huffman"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Huffman\HuffmanDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
|
||||
194
7zip/Archive/Cab/CabBlockInStream.cpp
Executable file
194
7zip/Archive/Cab/CabBlockInStream.cpp
Executable file
@@ -0,0 +1,194 @@
|
||||
// CabBlockInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/Alloc.h"
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "CabBlockInStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
static const UInt32 kBlockSize = (1 << 16);
|
||||
|
||||
bool CCabBlockInStream::Create()
|
||||
{
|
||||
if (!_buffer)
|
||||
_buffer = (Byte *)::MyAlloc(kBlockSize);
|
||||
return (_buffer != 0);
|
||||
}
|
||||
|
||||
CCabBlockInStream::~CCabBlockInStream()
|
||||
{
|
||||
MyFree(_buffer);
|
||||
}
|
||||
|
||||
class CCheckSum2
|
||||
{
|
||||
UInt32 m_Value;
|
||||
int m_Pos;
|
||||
Byte m_Hist[4];
|
||||
public:
|
||||
CCheckSum2(): m_Value(0){};
|
||||
void Init() { m_Value = 0; m_Pos = 0; }
|
||||
void Update(const void *data, UInt32 size);
|
||||
void FinishDataUpdate()
|
||||
{
|
||||
for (int i = 0; i < m_Pos; i++)
|
||||
m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
|
||||
}
|
||||
void UpdateUInt32(UInt32 v) { m_Value ^= v; }
|
||||
UInt32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum2::Update(const void *data, UInt32 size)
|
||||
{
|
||||
UInt32 checkSum = m_Value;
|
||||
const Byte *dataPointer = (const Byte *)data;
|
||||
|
||||
while (size != 0 && m_Pos != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
if (m_Pos == 0)
|
||||
for (int i = 0; i < 4; i++)
|
||||
checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
|
||||
}
|
||||
|
||||
int numWords = size / 4;
|
||||
|
||||
while (numWords-- != 0)
|
||||
{
|
||||
UInt32 temp = *dataPointer++;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 8;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 16;
|
||||
temp |= ((UInt32)(*dataPointer++)) << 24;
|
||||
checkSum ^= temp;
|
||||
}
|
||||
m_Value = checkSum;
|
||||
|
||||
size &= 3;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
m_Hist[m_Pos] = *dataPointer++;
|
||||
m_Pos = (m_Pos + 1) & 3;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
static const UInt32 kDataBlockHeaderSize = 8;
|
||||
|
||||
class CTempCabInBuffer2
|
||||
{
|
||||
public:
|
||||
Byte Buffer[kDataBlockHeaderSize];
|
||||
UInt32 Pos;
|
||||
Byte ReadByte()
|
||||
{
|
||||
return Buffer[Pos++];
|
||||
}
|
||||
UInt32 ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= (((UInt32)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
UInt16 ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= (((UInt16)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
|
||||
{
|
||||
CTempCabInBuffer2 inBuffer;
|
||||
inBuffer.Pos = 0;
|
||||
UInt32 processedSizeLoc;
|
||||
RINOK(ReadStream(_stream, inBuffer.Buffer, kDataBlockHeaderSize, &processedSizeLoc))
|
||||
if (processedSizeLoc != kDataBlockHeaderSize)
|
||||
return S_FALSE; // bad block
|
||||
|
||||
UInt32 checkSum = inBuffer.ReadUInt32();
|
||||
packSize = inBuffer.ReadUInt16();
|
||||
unpackSize = inBuffer.ReadUInt16();
|
||||
if (ReservedSize != 0)
|
||||
{
|
||||
RINOK(ReadStream(_stream, _buffer, ReservedSize, &processedSizeLoc));
|
||||
if(ReservedSize != processedSizeLoc)
|
||||
return S_FALSE; // bad block;
|
||||
}
|
||||
_pos = 0;
|
||||
CCheckSum2 checkSumCalc;
|
||||
checkSumCalc.Init();
|
||||
UInt32 packSize2 = packSize;
|
||||
if (MsZip && _size == 0)
|
||||
{
|
||||
if (packSize < 2)
|
||||
return S_FALSE; // bad block;
|
||||
Byte sig[2];
|
||||
RINOK(ReadStream(_stream, sig, 2, &processedSizeLoc));
|
||||
if(processedSizeLoc != 2)
|
||||
return S_FALSE;
|
||||
if (sig[0] != 0x43 || sig[1] != 0x4B)
|
||||
return S_FALSE;
|
||||
packSize2 -= 2;
|
||||
checkSumCalc.Update(sig, 2);
|
||||
}
|
||||
|
||||
if (kBlockSize - _size < packSize2)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 curSize = packSize2;
|
||||
if (curSize != 0)
|
||||
{
|
||||
RINOK(ReadStream(_stream, _buffer + _size, curSize, &processedSizeLoc));
|
||||
checkSumCalc.Update(_buffer + _size, processedSizeLoc);
|
||||
_size += processedSizeLoc;
|
||||
if (processedSizeLoc != curSize)
|
||||
return S_FALSE;
|
||||
}
|
||||
TotalPackSize = _size;
|
||||
|
||||
checkSumCalc.FinishDataUpdate();
|
||||
|
||||
bool dataError;
|
||||
if (checkSum == 0)
|
||||
dataError = false;
|
||||
else
|
||||
{
|
||||
checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
|
||||
dataError = (checkSumCalc.GetResult() != checkSum);
|
||||
}
|
||||
DataError |= dataError;
|
||||
return dataError ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize != 0)
|
||||
*processedSize = 0;
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
if (_size != 0)
|
||||
{
|
||||
size = MyMin(_size, size);
|
||||
memmove(data, _buffer + _pos, size);
|
||||
_pos += size;
|
||||
_size -= size;
|
||||
if (processedSize != 0)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
return S_OK; // no blocks data
|
||||
}
|
||||
|
||||
}}
|
||||
56
7zip/Archive/Cab/CabBlockInStream.h
Executable file
56
7zip/Archive/Cab/CabBlockInStream.h
Executable file
@@ -0,0 +1,56 @@
|
||||
// CabBlockInStream.cpp
|
||||
|
||||
#ifndef __CABBLOCKINSTREAM_H
|
||||
#define __CABBLOCKINSTREAM_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../../IStream.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CCabBlockInStream:
|
||||
public ISequentialInStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
Byte *_buffer;
|
||||
UInt32 _pos;
|
||||
UInt32 _size;
|
||||
int _align;
|
||||
|
||||
public:
|
||||
UInt32 TotalPackSize;
|
||||
UInt32 ReservedSize;
|
||||
bool DataError;
|
||||
bool MsZip;
|
||||
|
||||
CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), _align(0), TotalPackSize(0) {}
|
||||
~CCabBlockInStream();
|
||||
bool Create();
|
||||
void SetStream(ISequentialInStream *stream) { _stream = stream; }
|
||||
|
||||
void InitForNewFolder()
|
||||
{
|
||||
_align = 0;
|
||||
TotalPackSize = 0;
|
||||
}
|
||||
|
||||
void InitForNewBlock()
|
||||
{
|
||||
_size = 0;
|
||||
_align = (_align + (int)TotalPackSize) & 1;
|
||||
}
|
||||
|
||||
int GetAlign() const { return _align; }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,73 +0,0 @@
|
||||
// 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 *decoder): m_Decoder(decoder) {}
|
||||
~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;
|
||||
|
||||
if (!m_OutStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_InStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
m_InStream.SetStream(inStream);
|
||||
m_InStream.Init(m_ReservedSize, m_NumInDataBlocks);
|
||||
m_OutStream.SetStream(outStream);
|
||||
m_OutStream.Init();
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,41 +0,0 @@
|
||||
// CabCopyDecoder.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_COPY_DECODER_H
|
||||
#define __ARCHIVE_CAB_COPY_DECODER_H
|
||||
|
||||
#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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,10 +37,7 @@ public:
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType);
|
||||
|
||||
private:
|
||||
CObjectVector<NHeader::CFolder> m_Folders;
|
||||
CObjectVector<CItem> m_Files;
|
||||
CInArchiveInfo m_ArchiveInfo;
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
CMvDatabaseEx m_Database;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,53 +9,15 @@ namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NHeader{
|
||||
|
||||
namespace NArchive {
|
||||
|
||||
namespace NArchive
|
||||
{
|
||||
extern UInt32 kSignature;
|
||||
|
||||
namespace NFlags
|
||||
{
|
||||
const int kPrevCabinet = 0x0001;
|
||||
const int kNextCabinet = 0x0002;
|
||||
const int kReservePresent = 0x0004;
|
||||
}
|
||||
|
||||
const UInt32 kArchiveHeaderSize = 36;
|
||||
/*
|
||||
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
|
||||
};
|
||||
*/
|
||||
|
||||
const UInt32 kPerDataSizesHeaderSize = 4;
|
||||
|
||||
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
|
||||
@@ -66,17 +28,6 @@ namespace NCompressionMethodMajor
|
||||
const Byte kLZX = 3;
|
||||
}
|
||||
|
||||
const UInt32 kFolderHeaderSize = 8;
|
||||
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
|
||||
@@ -84,34 +35,8 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const UInt32 kFileHeaderSize = 16;
|
||||
/*
|
||||
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
|
||||
};
|
||||
*/
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
#include "Common/MyCom.h"
|
||||
#include "CabIn.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NCab{
|
||||
@@ -14,7 +15,7 @@ namespace NCab{
|
||||
static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
@@ -23,7 +24,7 @@ static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
|
||||
static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||
if(realProcessedSize != size)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return S_OK;
|
||||
@@ -37,25 +38,12 @@ static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 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);
|
||||
}
|
||||
}
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
if (_blockPos >= _blockSize)
|
||||
throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
|
||||
return _block[_blockPos++];
|
||||
Byte b;
|
||||
if (!inBuffer.ReadByte(b))
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
return b;
|
||||
}
|
||||
|
||||
UInt16 CInArchive::ReadUInt16()
|
||||
@@ -80,20 +68,38 @@ UInt32 CInArchive::ReadUInt32()
|
||||
return value;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CInArchiveInfo &inArchiveInfo,
|
||||
CObjectVector<NHeader::CFolder> &folders,
|
||||
CObjectVector<CItem> &files,
|
||||
CProgressVirt *progressVirt)
|
||||
AString CInArchive::SafeReadName()
|
||||
{
|
||||
UInt64 startPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &startPosition));
|
||||
AString name;
|
||||
while(true)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
if (b == 0)
|
||||
return name;
|
||||
name += (char)b;
|
||||
}
|
||||
}
|
||||
|
||||
// NHeader::NArchive::CBlock archiveHeader;
|
||||
void CInArchive::ReadOtherArchive(COtherArchive &oa)
|
||||
{
|
||||
oa.FileName = SafeReadName();
|
||||
oa.DiskName = SafeReadName();
|
||||
}
|
||||
|
||||
void CInArchive::Skeep(size_t size)
|
||||
{
|
||||
while (size-- != 0)
|
||||
ReadByte();
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open2(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CDatabase &database)
|
||||
{
|
||||
database.Clear();
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition));
|
||||
|
||||
{
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
@@ -117,141 +123,219 @@ HRESULT CInArchive::Open(IInStream *inStream,
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
startPosition += inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
database.StartPosition += inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
}
|
||||
RINOK(inStream->Seek(startPosition, STREAM_SEEK_SET, NULL));
|
||||
|
||||
RINOK(ReadBytes(inStream, _block, NHeader::NArchive::kArchiveHeaderSize));
|
||||
_blockSize = NHeader::NArchive::kArchiveHeaderSize;
|
||||
_blockPos = 0;
|
||||
CInArchiveInfo &archiveInfo = database.ArchiveInfo;
|
||||
|
||||
ReadUInt32(); // Signature; // cabinet file signature
|
||||
// if (archiveHeader.Signature != NHeader::NArchive::kSignature)
|
||||
// return S_FALSE;
|
||||
archiveInfo.Size = ReadUInt32(); // size of this cabinet file in bytes
|
||||
if (ReadUInt32() != 0)
|
||||
return S_FALSE;
|
||||
archiveInfo.FileHeadersOffset = ReadUInt32(); // offset of the first CFFILE entry
|
||||
if (ReadUInt32() != 0)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 reserved1 = ReadUInt32();
|
||||
UInt32 size = ReadUInt32(); // size of this cabinet file in bytes
|
||||
UInt32 reserved2 = ReadUInt32();
|
||||
UInt32 fileOffset = ReadUInt32(); // offset of the first CFFILE entry
|
||||
UInt32 reserved3 = ReadUInt32();
|
||||
archiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
|
||||
archiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
|
||||
archiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
|
||||
archiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
archiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
archiveInfo.SetID = ReadUInt16(); // must be the same for all cabinets in a set
|
||||
archiveInfo.CabinetNumber = ReadUInt16(); // number of this cabinet file in a set
|
||||
|
||||
inArchiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
|
||||
inArchiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
|
||||
inArchiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
|
||||
inArchiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
inArchiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet
|
||||
UInt16 setID = ReadUInt16(); // must be the same for all cabinets in a set
|
||||
UInt16 cabinetNumber = ReadUInt16(); // number of this cabinet file in a set
|
||||
|
||||
if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
|
||||
throw CInArchiveException(CInArchiveException::kUnsupported);
|
||||
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
if (archiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(SafeRead(inStream, _block, NHeader::NArchive::kPerDataSizesHeaderSize));
|
||||
_blockSize = NHeader::NArchive::kPerDataSizesHeaderSize;
|
||||
_blockPos = 0;
|
||||
archiveInfo.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
|
||||
archiveInfo.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
|
||||
archiveInfo.PerDataBlockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
|
||||
|
||||
inArchiveInfo.PerDataSizes.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
|
||||
inArchiveInfo.PerDataSizes.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
|
||||
inArchiveInfo.PerDataSizes.PerDatablockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
|
||||
RINOK(inStream->Seek(inArchiveInfo.PerDataSizes.PerCabinetAreaSize,
|
||||
STREAM_SEEK_CUR, NULL));
|
||||
Skeep(archiveInfo.PerCabinetAreaSize);
|
||||
}
|
||||
|
||||
{
|
||||
UInt64 foldersStartPosition;
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &foldersStartPosition));
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
if ((inArchiveInfo.Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0)
|
||||
{
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousCabinetName);
|
||||
SafeReadName(inBuffer, inArchiveInfo.PreviousDiskName);
|
||||
}
|
||||
if ((inArchiveInfo.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 (archiveInfo.IsTherePrev())
|
||||
ReadOtherArchive(archiveInfo.PreviousArchive);
|
||||
if (archiveInfo.IsThereNext())
|
||||
ReadOtherArchive(archiveInfo.NextArchive);
|
||||
}
|
||||
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UInt64 numFiles = inArchiveInfo.NumFiles;
|
||||
RINOK(progressVirt->SetTotal(&numFiles));
|
||||
}
|
||||
folders.Clear();
|
||||
int i;
|
||||
for(i = 0; i < inArchiveInfo.NumFolders; i++)
|
||||
for(i = 0; i < archiveInfo.NumFolders; i++)
|
||||
{
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UInt64 numFiles = 0;
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
NHeader::CFolder folder;
|
||||
RINOK(SafeRead(inStream, _block, NHeader::kFolderHeaderSize));
|
||||
_blockSize = NHeader::kFolderHeaderSize;
|
||||
_blockPos = 0;
|
||||
CFolder folder;
|
||||
|
||||
folder.DataStart = ReadUInt32();
|
||||
folder.NumDataBlocks = ReadUInt16();
|
||||
folder.CompressionTypeMajor = ReadByte();
|
||||
folder.CompressionTypeMinor = ReadByte();
|
||||
|
||||
if (inArchiveInfo.ReserveBlockPresent())
|
||||
{
|
||||
RINOK(inStream->Seek(
|
||||
inArchiveInfo.PerDataSizes.PerFolderAreaSize, STREAM_SEEK_CUR, NULL));
|
||||
}
|
||||
folder.DataStart += (UInt32)startPosition;
|
||||
folders.Add(folder);
|
||||
Skeep(archiveInfo.PerFolderAreaSize);
|
||||
database.Folders.Add(folder);
|
||||
}
|
||||
|
||||
RINOK(inStream->Seek(startPosition + fileOffset,
|
||||
STREAM_SEEK_SET, NULL));
|
||||
RINOK(inStream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL));
|
||||
|
||||
::CInBuffer inBuffer;
|
||||
if (!inBuffer.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
files.Clear();
|
||||
if (progressVirt != NULL)
|
||||
for(i = 0; i < archiveInfo.NumFiles; i++)
|
||||
{
|
||||
UInt64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
for(i = 0; i < inArchiveInfo.NumFiles; i++)
|
||||
{
|
||||
SafeInByteRead(inBuffer, _block, NHeader::kFileHeaderSize);
|
||||
_blockSize = NHeader::kFileHeaderSize;
|
||||
_blockPos = 0;
|
||||
CItem item;
|
||||
item.UnPackSize = ReadUInt32();
|
||||
item.UnPackOffset = ReadUInt32();
|
||||
item.Size = ReadUInt32();
|
||||
item.Offset = ReadUInt32();
|
||||
item.FolderIndex = ReadUInt16();
|
||||
if (item.FolderIndex > inArchiveInfo.NumFolders)
|
||||
return S_FALSE;
|
||||
UInt16 pureDate = ReadUInt16();
|
||||
UInt16 pureTime = ReadUInt16();
|
||||
item.Time = ((UInt32(pureDate) << 16)) | pureTime;
|
||||
item.Attributes = ReadUInt16();
|
||||
SafeReadName(inBuffer, item.Name);
|
||||
files.Add(item);
|
||||
if (progressVirt != NULL)
|
||||
{
|
||||
UInt64 numFiles = files.Size();
|
||||
RINOK(progressVirt->SetCompleted(&numFiles));
|
||||
}
|
||||
item.Name = SafeReadName();
|
||||
int folderIndex = item.GetFolderIndex(database.Folders.Size());
|
||||
if (folderIndex >= database.Folders.Size())
|
||||
return S_FALSE;
|
||||
database.Items.Add(item);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
HRESULT CInArchive::Open(
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CDatabaseEx &database)
|
||||
{
|
||||
return Open2(database.Stream, searchHeaderSizeLimit, database);
|
||||
}
|
||||
|
||||
|
||||
static int CompareMvItems2(const CMvItem *p1, const CMvItem *p2)
|
||||
{
|
||||
RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
|
||||
return MyCompare(p1->ItemIndex, p2->ItemIndex);
|
||||
}
|
||||
|
||||
static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
|
||||
{
|
||||
const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
|
||||
const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];
|
||||
const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];;
|
||||
bool isDir1 = item1.IsDirectory();
|
||||
bool isDir2 = item2.IsDirectory();
|
||||
if (isDir1 && !isDir2)
|
||||
return -1;
|
||||
if (isDir2 && !isDir1)
|
||||
return 1;
|
||||
int f1 = mvDb.GetFolderIndex(p1);
|
||||
int f2 = mvDb.GetFolderIndex(p2);
|
||||
RINOZ(MyCompare(f1, f2));
|
||||
RINOZ(MyCompare(item1.Offset, item2.Offset));
|
||||
RINOZ(MyCompare(item1.Size, item2.Size));
|
||||
return CompareMvItems2(p1, p2);
|
||||
}
|
||||
|
||||
bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
|
||||
{
|
||||
const CMvItem *p1 = &Items[i1];
|
||||
const CMvItem *p2 = &Items[i2];
|
||||
const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];
|
||||
const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
|
||||
const CItem &item1 = db1.Items[p1->ItemIndex];
|
||||
const CItem &item2 = db2.Items[p2->ItemIndex];;
|
||||
int f1 = GetFolderIndex(p1);
|
||||
int f2 = GetFolderIndex(p2);
|
||||
if (f1 != f2)
|
||||
return false;
|
||||
if (item1.Offset != item2.Offset)
|
||||
return false;
|
||||
if (item1.Size != item2.Size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMvDatabaseEx::FillSortAndShrink()
|
||||
{
|
||||
Items.Clear();
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
int offset = 0;
|
||||
for (int v = 0; v < Volumes.Size(); v++)
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[v];
|
||||
int curOffset = offset;
|
||||
if (db.IsTherePrevFolder())
|
||||
curOffset--;
|
||||
StartFolderOfVol.Add(curOffset);
|
||||
offset += db.GetNumberOfNewFolders();
|
||||
|
||||
CMvItem mvItem;
|
||||
mvItem.VolumeIndex = v;
|
||||
for (int i = 0 ; i < db.Items.Size(); i++)
|
||||
{
|
||||
mvItem.ItemIndex = i;
|
||||
Items.Add(mvItem);
|
||||
}
|
||||
}
|
||||
|
||||
Items.Sort(CompareMvItems, (void *)this);
|
||||
int j = 1;
|
||||
int i;
|
||||
for (i = 1; i < Items.Size(); i++)
|
||||
if (!AreItemsEqual(i, i -1))
|
||||
Items[j++] = Items[i];
|
||||
Items.DeleteFrom(j);
|
||||
|
||||
for (i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
const CMvItem &mvItem = Items[i];
|
||||
int folderIndex = GetFolderIndex(&mvItem);
|
||||
if (folderIndex >= FolderStartFileIndex.Size())
|
||||
FolderStartFileIndex.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool CMvDatabaseEx::Check()
|
||||
{
|
||||
for (int v = 1; v < Volumes.Size(); v++)
|
||||
{
|
||||
const CDatabaseEx &db1 = Volumes[v];
|
||||
if (db1.IsTherePrevFolder())
|
||||
{
|
||||
const CDatabaseEx &db0 = Volumes[v - 1];
|
||||
if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
|
||||
return false;
|
||||
const CFolder &f0 = db0.Folders.Back();
|
||||
const CFolder &f1 = db1.Folders.Front();
|
||||
if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||
|
||||
f0.CompressionTypeMinor != f1.CompressionTypeMinor)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
UInt64 maxPos = 0;
|
||||
int prevFolder = -2;
|
||||
for(int i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
const CMvItem &mvItem = Items[i];
|
||||
int fIndex = GetFolderIndex(&mvItem);
|
||||
if (fIndex >= FolderStartFileIndex.Size())
|
||||
return false;
|
||||
const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
|
||||
if (item.IsDirectory())
|
||||
continue;
|
||||
int folderIndex = GetFolderIndex(&mvItem);
|
||||
if (folderIndex != prevFolder)
|
||||
{
|
||||
prevFolder = folderIndex;
|
||||
maxPos = 0;
|
||||
continue;
|
||||
}
|
||||
if (item.Offset < maxPos)
|
||||
return false;
|
||||
maxPos = item.GetEndOffset();
|
||||
if (maxPos < item.Offset)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __ARCHIVE_CAB_IN_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
#include "CabHeader.h"
|
||||
#include "CabItem.h"
|
||||
|
||||
@@ -22,10 +23,14 @@ public:
|
||||
CInArchiveException(CCauseType cause) : Cause(cause) {}
|
||||
};
|
||||
|
||||
class CInArchiveInfo
|
||||
struct COtherArchive
|
||||
{
|
||||
AString FileName;
|
||||
AString DiskName;
|
||||
};
|
||||
|
||||
struct CArchiveInfo
|
||||
{
|
||||
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 */
|
||||
@@ -35,39 +40,125 @@ public:
|
||||
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;
|
||||
bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; }
|
||||
bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; }
|
||||
|
||||
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 GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }
|
||||
|
||||
COtherArchive PreviousArchive;
|
||||
COtherArchive NextArchive;
|
||||
|
||||
CArchiveInfo()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
PerCabinetAreaSize = 0;
|
||||
PerFolderAreaSize = 0;
|
||||
PerDataBlockAreaSize = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CProgressVirt
|
||||
struct CInArchiveInfo: public CArchiveInfo
|
||||
{
|
||||
UInt32 Size; /* size of this cabinet file in bytes */
|
||||
UInt32 FileHeadersOffset; //offset of the first CFFILE entry
|
||||
};
|
||||
|
||||
|
||||
class CDatabase
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;
|
||||
STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
|
||||
UInt64 StartPosition;
|
||||
CInArchiveInfo ArchiveInfo;
|
||||
CObjectVector<CFolder> Folders;
|
||||
CObjectVector<CItem> Items;
|
||||
void Clear()
|
||||
{
|
||||
ArchiveInfo.Clear();
|
||||
Folders.Clear();
|
||||
Items.Clear();
|
||||
}
|
||||
bool IsTherePrevFolder() const
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
if (Items[i].ContinuedFromPrev())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int GetNumberOfNewFolders() const
|
||||
{
|
||||
int res = Folders.Size();
|
||||
if (IsTherePrevFolder())
|
||||
res--;
|
||||
return res;
|
||||
}
|
||||
UInt32 GetFileOffset(int index) const { return Items[index].Offset; }
|
||||
UInt32 GetFileSize(int index) const { return Items[index].Size; }
|
||||
};
|
||||
|
||||
const UInt32 kMaxBlockSize = NHeader::NArchive::kArchiveHeaderSize;
|
||||
class CDatabaseEx: public CDatabase
|
||||
{
|
||||
public:
|
||||
CMyComPtr<IInStream> Stream;
|
||||
};
|
||||
|
||||
struct CMvItem
|
||||
{
|
||||
int VolumeIndex;
|
||||
int ItemIndex;
|
||||
};
|
||||
|
||||
class CMvDatabaseEx
|
||||
{
|
||||
bool AreItemsEqual(int i1, int i2);
|
||||
public:
|
||||
CObjectVector<CDatabaseEx> Volumes;
|
||||
CRecordVector<CMvItem> Items;
|
||||
CRecordVector<int> StartFolderOfVol;
|
||||
CRecordVector<int> FolderStartFileIndex;
|
||||
int GetFolderIndex(const CMvItem *mvi) const
|
||||
{
|
||||
const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
|
||||
return StartFolderOfVol[mvi->VolumeIndex] +
|
||||
db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
Volumes.Clear();
|
||||
Items.Clear();
|
||||
StartFolderOfVol.Clear();
|
||||
FolderStartFileIndex.Clear();
|
||||
}
|
||||
void FillSortAndShrink();
|
||||
bool Check();
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
UInt16 _blockSize;
|
||||
Byte _block[kMaxBlockSize];
|
||||
UInt32 _blockPos;
|
||||
CInBuffer inBuffer;
|
||||
|
||||
Byte ReadByte();
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32();
|
||||
public:
|
||||
HRESULT Open(IInStream *inStream,
|
||||
AString SafeReadName();
|
||||
void Skeep(size_t size);
|
||||
void ReadOtherArchive(COtherArchive &oa);
|
||||
|
||||
HRESULT Open2(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CInArchiveInfo &inArchiveInfo,
|
||||
CObjectVector<NHeader::CFolder> &folders,
|
||||
CObjectVector<CItem> &files,
|
||||
CProgressVirt *progressVirt);
|
||||
CDatabase &database);
|
||||
public:
|
||||
HRESULT Open(
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CDatabaseEx &database);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
// Archive/CabInBuffer.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/Alloc.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
#include "../../../Windows/Defs.h"
|
||||
#include "CabInBuffer.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
static const UInt32 kDataBlockHeaderSize = 8;
|
||||
/*
|
||||
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
|
||||
};
|
||||
*/
|
||||
|
||||
class CTempCabInBuffer
|
||||
{
|
||||
public:
|
||||
Byte *Buffer;
|
||||
UInt32 Size;
|
||||
UInt32 Pos;
|
||||
Byte ReadByte()
|
||||
{
|
||||
if (Pos >= Size)
|
||||
throw "overflow";
|
||||
return Buffer[Pos++];
|
||||
}
|
||||
UInt32 ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= (((UInt32)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
UInt16 ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= (((UInt16)ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
bool CInBuffer::Create(UInt32 bufferSize)
|
||||
{
|
||||
const UInt32 kMinBlockSize = 1;
|
||||
if (bufferSize < kMinBlockSize)
|
||||
bufferSize = kMinBlockSize;
|
||||
if (m_Buffer != 0 && m_BufferSize == bufferSize)
|
||||
return true;
|
||||
Free();
|
||||
m_BufferSize = bufferSize;
|
||||
m_Buffer = (Byte *)::BigAlloc(bufferSize);
|
||||
return (m_Buffer != 0);
|
||||
}
|
||||
|
||||
void CInBuffer::Free()
|
||||
{
|
||||
BigFree(m_Buffer);
|
||||
m_Buffer = 0;
|
||||
}
|
||||
|
||||
void CInBuffer::Init(Byte reservedSize, UInt32 numBlocks)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumBlocks = numBlocks;
|
||||
m_CurrentBlockIndex = 0;
|
||||
m_ProcessedSize = 0;
|
||||
m_Pos = 0;
|
||||
m_NumReadBytesInBuffer = 0;
|
||||
}
|
||||
|
||||
class CCheckSum
|
||||
{
|
||||
UInt32 m_Value;
|
||||
public:
|
||||
CCheckSum(): m_Value(0){};
|
||||
void Init() { m_Value = 0; }
|
||||
void Update(const void *data, UInt32 size);
|
||||
void UpdateUInt32(UInt32 v) { m_Value ^= v; }
|
||||
UInt32 GetResult() const { return m_Value; }
|
||||
};
|
||||
|
||||
void CCheckSum::Update(const void *data, UInt32 size)
|
||||
{
|
||||
UInt32 checkSum = m_Value;
|
||||
const Byte *dataPointer = (const Byte *)data;
|
||||
int numUINT32Words = size / 4; // Number of ULONGs
|
||||
|
||||
UInt32 temp;
|
||||
while (numUINT32Words-- > 0)
|
||||
{
|
||||
temp = *dataPointer++;
|
||||
temp |= (((UInt32)(*dataPointer++)) << 8);
|
||||
temp |= (((UInt32)(*dataPointer++)) << 16);
|
||||
temp |= (((UInt32)(*dataPointer++)) << 24);
|
||||
checkSum ^= temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
int rem = (size & 3);
|
||||
if (rem >= 3)
|
||||
temp |= (((UInt32)(*dataPointer++)) << 16);
|
||||
if (rem >= 2)
|
||||
temp |= (((UInt32)(*dataPointer++)) << 8);
|
||||
if (rem >= 1)
|
||||
temp |= *dataPointer++;
|
||||
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;
|
||||
|
||||
Byte buffer[kDataBlockHeaderSize];
|
||||
UInt32 numProcessedBytes;
|
||||
RINOK(m_Stream->Read(buffer, kDataBlockHeaderSize, &numProcessedBytes));
|
||||
if (numProcessedBytes != kDataBlockHeaderSize)
|
||||
throw "bad block";
|
||||
|
||||
CTempCabInBuffer inBuffer;
|
||||
inBuffer.Size = kDataBlockHeaderSize;
|
||||
inBuffer.Buffer = (Byte *)buffer;
|
||||
inBuffer.Pos = 0;
|
||||
|
||||
UInt32 checkSum = inBuffer.ReadUInt32(); // checksum of this CFDATA entry
|
||||
UInt16 packSize = inBuffer.ReadUInt16(); // number of compressed bytes in this block
|
||||
UInt16 unPackSize = inBuffer.ReadUInt16(); // number of uncompressed bytes in this 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, packSize, &m_NumReadBytesInBuffer));
|
||||
if (m_NumReadBytesInBuffer != packSize)
|
||||
throw "bad block";
|
||||
|
||||
// Cab specification:
|
||||
// checkSum: May be set to zero if the checksum is not supplied.
|
||||
// but seems it's stupid rule.
|
||||
if (checkSum == 0)
|
||||
dataAreCorrect = true;
|
||||
else
|
||||
{
|
||||
CCheckSum checkSumCalc;
|
||||
checkSumCalc.Update(m_Buffer, packSize);
|
||||
checkSumCalc.UpdateUInt32(packSize | (((UInt32)unPackSize) << 16));
|
||||
dataAreCorrect = (checkSumCalc.GetResult() == checkSum);
|
||||
}
|
||||
|
||||
m_Pos = 0;
|
||||
uncompressedSize = unPackSize;
|
||||
|
||||
m_CurrentBlockIndex++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,66 +0,0 @@
|
||||
// Archive/CabInBuffer.h
|
||||
|
||||
#ifndef __ARCHIVE_CAB_INBUFFER_H
|
||||
#define __ARCHIVE_CAB_INBUFFER_H
|
||||
|
||||
#include "../../IStream.h"
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
class CInBuffer
|
||||
{
|
||||
UInt64 m_ProcessedSize;
|
||||
UInt32 m_Pos;
|
||||
UInt32 m_NumReadBytesInBuffer;
|
||||
Byte *m_Buffer;
|
||||
CMyComPtr<ISequentialInStream> m_Stream;
|
||||
UInt32 m_BufferSize;
|
||||
|
||||
UInt32 m_NumBlocks;
|
||||
UInt32 m_CurrentBlockIndex;
|
||||
UInt32 m_ReservedSize;
|
||||
|
||||
public:
|
||||
CInBuffer(): m_Buffer(0) {}
|
||||
~CInBuffer() { Free(); }
|
||||
bool Create(UInt32 bufferSize);
|
||||
void Free();
|
||||
|
||||
void SetStream(ISequentialInStream *inStream) { m_Stream = inStream; }
|
||||
void ReleaseStream() { m_Stream.Release(); }
|
||||
|
||||
void Init(Byte reservedSize, UInt32 numBlocks);
|
||||
void Init() {}
|
||||
|
||||
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
|
||||
@@ -1,7 +1,7 @@
|
||||
// Archive/Cab/ItemInfo.h
|
||||
// Archive/CabItem.h
|
||||
|
||||
#ifndef __ARCHIVE_RAR_ITEMINFO_H
|
||||
#define __ARCHIVE_RAR_ITEMINFO_H
|
||||
#ifndef __ARCHIVE_CAB_ITEM_H
|
||||
#define __ARCHIVE_CAB_ITEM_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
#include "Common/String.h"
|
||||
@@ -10,23 +10,53 @@
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
|
||||
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 GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); }
|
||||
};
|
||||
|
||||
class CItem
|
||||
{
|
||||
public:
|
||||
UInt16 Flags;
|
||||
UInt64 UnPackSize;
|
||||
UInt32 UnPackOffset;
|
||||
UInt16 FolderIndex;
|
||||
AString Name;
|
||||
UInt32 Offset;
|
||||
UInt32 Size;
|
||||
UInt32 Time;
|
||||
UInt16 Attributes;
|
||||
UInt32 GetWinAttributes() const { return Attributes & (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
|
||||
UInt16 FolderIndex;
|
||||
UInt16 Flags;
|
||||
UInt16 Attributes;
|
||||
UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
|
||||
UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
|
||||
bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }
|
||||
bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
|
||||
AString Name;
|
||||
|
||||
bool ContinuedFromPrev() const
|
||||
{
|
||||
return
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) ||
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
|
||||
}
|
||||
bool ContinuedToNext() const
|
||||
{
|
||||
return
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedToNext) ||
|
||||
(FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
|
||||
}
|
||||
|
||||
int GetFolderIndex(int numFolders) const
|
||||
{
|
||||
if (ContinuedFromPrev())
|
||||
return 0;
|
||||
if (ContinuedToNext())
|
||||
return (numFolders - 1);
|
||||
return FolderIndex;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
#include "CabHandler.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110060000}
|
||||
// {23170F69-40C1-278A-1000-000110080000}
|
||||
DEFINE_GUID(CLSID_CCabHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
// 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:
|
||||
bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
||||
void SetStream(ISequentialInStream *s) { m_Stream.SetStream(s); }
|
||||
void ReleaseStream() { m_Stream.ReleaseStream(); }
|
||||
void Init(Byte reservedSize, UInt32 numBlocks)
|
||||
{
|
||||
m_Stream.Init(reservedSize, numBlocks);
|
||||
}
|
||||
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 b0 = m_Stream.ReadByte();
|
||||
Byte b1 = m_Stream.ReadByte();
|
||||
m_Value = (m_Value << 8) | b1;
|
||||
m_Value = (m_Value << 8) | b0;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 GetValue(UInt32 numBits)
|
||||
{
|
||||
return ((m_Value >> ((32 - kNumValueBits) - m_BitPos)) & kBitDecoderValueMask) >>
|
||||
(kNumValueBits - numBits);
|
||||
}
|
||||
|
||||
void MovePos(UInt32 numBits)
|
||||
{
|
||||
m_BitPos += numBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
UInt32 ReadBits(UInt32 numBits)
|
||||
{
|
||||
UInt32 res = GetValue(numBits);
|
||||
MovePos(numBits);
|
||||
return res;
|
||||
}
|
||||
UInt32 ReadBitsBig(UInt32 numBits)
|
||||
{
|
||||
UInt32 numBits0 = numBits / 2;
|
||||
UInt32 numBits1 = numBits - numBits0;
|
||||
UInt32 res = ReadBits(numBits0) << numBits1;
|
||||
return res + ReadBits(numBits1);
|
||||
}
|
||||
|
||||
Byte DirectReadByte()
|
||||
{
|
||||
if (m_BitPos == kNumBigValueBits)
|
||||
return m_Stream.ReadByte();
|
||||
Byte res;
|
||||
switch(m_BitPos)
|
||||
{
|
||||
case 0:
|
||||
res = Byte(m_Value >> 16);
|
||||
break;
|
||||
case 8:
|
||||
res = Byte(m_Value >> 24);
|
||||
break;
|
||||
case 16:
|
||||
res = Byte(m_Value);
|
||||
break;
|
||||
case 24:
|
||||
res = Byte(m_Value >> 8);
|
||||
break;
|
||||
}
|
||||
m_BitPos += 8;
|
||||
return res;
|
||||
}
|
||||
|
||||
HRESULT ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect)
|
||||
{ return m_Stream.ReadBlock(uncompressedSize, dataAreCorrect); }
|
||||
};
|
||||
|
||||
|
||||
}}}}
|
||||
|
||||
#endif
|
||||
@@ -1,110 +0,0 @@
|
||||
// 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
|
||||
@@ -1,310 +0,0 @@
|
||||
// Archive/Cab/LZXDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "LZXDecoder.h"
|
||||
|
||||
#include "Common/Defs.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
static const UInt32 kHistorySize = (1 << 21);
|
||||
|
||||
CDecoder::CDecoder()
|
||||
{
|
||||
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;
|
||||
|
||||
if (!m_OutWindowStream.Create(kHistorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
m_OutWindowStream.SetStream(m_i86TranslationOutStream);
|
||||
m_OutWindowStream.Init();
|
||||
|
||||
m_InBitStream.SetStream(inStream);
|
||||
m_InBitStream.Init(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.PutByte(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.PutByte(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.CopyBlock(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.CopyBlock(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;
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -1,95 +0,0 @@
|
||||
// Archive/Cab/LZXDecoder.h
|
||||
|
||||
#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 "LZXConst.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
const int kMainTableSize = 256 + kNumPosSlotLenSlotSymbols;
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
NBitStream::CDecoder m_InBitStream;
|
||||
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kNumLenSymbols> m_LenDecoder;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
|
||||
|
||||
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
|
||||
@@ -1,30 +0,0 @@
|
||||
// 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
|
||||
@@ -1,93 +0,0 @@
|
||||
// Archive/Cab/LZXi86Converter.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/Defs.h"
|
||||
|
||||
#include "LZXi86Converter.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NLZX {
|
||||
|
||||
static const int kResidue = 6 + 4;
|
||||
|
||||
void Ci86TranslationOutStream::MakeTranslation()
|
||||
{
|
||||
if (m_Pos <= kResidue)
|
||||
return;
|
||||
UInt32 numBytes = m_Pos - kResidue;
|
||||
for (UInt32 i = 0; i < numBytes;)
|
||||
{
|
||||
if (m_Buffer[i] == 0xE8)
|
||||
{
|
||||
i++;
|
||||
Int32 absValue = 0;
|
||||
int j;
|
||||
for(j = 0; j < 4; j++)
|
||||
absValue += UInt32(m_Buffer[i + j]) << (j * 8);
|
||||
|
||||
Int32 pos = m_ProcessedSize + i - 1;
|
||||
UInt32 offset;
|
||||
if (absValue < -pos || absValue >= Int32(m_TranslationSize))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (absValue >= 0) ?
|
||||
absValue - pos :
|
||||
absValue + m_TranslationSize;
|
||||
for(j = 0; j < 4; j++)
|
||||
{
|
||||
m_Buffer[i + j] = Byte(offset & 0xFF);
|
||||
offset >>= 8;
|
||||
}
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP Ci86TranslationOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (!m_TranslationMode)
|
||||
return m_Stream->Write(data, size, processedSize);
|
||||
|
||||
UInt32 realProcessedSize = 0;
|
||||
|
||||
while (realProcessedSize < size)
|
||||
{
|
||||
UInt32 writeSize = MyMin(size - realProcessedSize, kUncompressedBlockSize - m_Pos);
|
||||
memmove(m_Buffer + m_Pos, (const Byte *)data + realProcessedSize, writeSize);
|
||||
m_Pos += writeSize;
|
||||
realProcessedSize += writeSize;
|
||||
if (m_Pos == kUncompressedBlockSize)
|
||||
{
|
||||
RINOK(Flush());
|
||||
}
|
||||
}
|
||||
if (processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP Ci86TranslationOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -1,50 +0,0 @@
|
||||
// Archive/Cab/LZXi86Converter.h
|
||||
|
||||
#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;
|
||||
|
||||
void MakeTranslation();
|
||||
public:
|
||||
Ci86TranslationOutStream(): m_Pos(0) {}
|
||||
~Ci86TranslationOutStream() { Flush(); }
|
||||
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
public:
|
||||
void Init(ISequentialOutStream *outStream, bool translationMode, UInt32 translationSize)
|
||||
{
|
||||
m_Stream = outStream;
|
||||
m_TranslationMode = translationMode;
|
||||
m_TranslationSize = translationSize;
|
||||
m_ProcessedSize = 0;
|
||||
m_Pos = 0;
|
||||
}
|
||||
void ReleaseStream() { m_Stream.Release(); }
|
||||
HRESULT Flush();
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,92 +0,0 @@
|
||||
// MSZipConst.h
|
||||
|
||||
#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
|
||||
@@ -1,268 +0,0 @@
|
||||
// Archive/Cab/MSZipDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MSZipDecoder.h"
|
||||
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NCab {
|
||||
namespace NMSZip {
|
||||
|
||||
CDecoder::CDecoder(){}
|
||||
|
||||
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;
|
||||
|
||||
if (!m_OutWindowStream.Create(kHistorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
m_OutWindowStream.Init(false);
|
||||
|
||||
m_InBitStream.SetStream(inStream);
|
||||
m_InBitStream.InitMain(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.PutByte(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.PutByte(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.CopyBlock(distance, length);
|
||||
nowPos += length;
|
||||
uncompressedCFDataCurrentValue += length;
|
||||
}
|
||||
else if (number == kReadTableNumber)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
throw CDecoderException(CDecoderException::kData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}}
|
||||
@@ -1,85 +0,0 @@
|
||||
// Archive/Cab/MSZipDecoder.h
|
||||
|
||||
#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"
|
||||
#include "MSZipConst.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(Byte reservedSize, UInt32 aNumBlocks)
|
||||
{
|
||||
m_Stream.Init(reservedSize, aNumBlocks);
|
||||
Init();
|
||||
}
|
||||
HRESULT ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect)
|
||||
{
|
||||
return m_Stream.ReadBlock(uncompressedSize, dataAreCorrect);
|
||||
}
|
||||
};
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLZOutWindow m_OutWindowStream;
|
||||
CMSZipBitDecoder m_InBitStream;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticMainTableSize> m_MainDecoder;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kStaticDistTableSize> m_DistDecoder;
|
||||
NCompress::NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
|
||||
|
||||
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 reservedSize, UInt32 numInDataBlocks)
|
||||
{
|
||||
m_ReservedSize = reservedSize;
|
||||
m_NumInDataBlocks = numInDataBlocks;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
// DeflateExtConst.h
|
||||
|
||||
#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
|
||||
@@ -5,14 +5,10 @@ LIBS = $(LIBS) oleaut32.lib user32.lib
|
||||
|
||||
CAB_OBJS = \
|
||||
$O\DllExports.obj \
|
||||
$O\CabCopyDecoder.obj \
|
||||
$O\CabBlockInStream.obj \
|
||||
$O\CabHandler.obj \
|
||||
$O\CabHeader.obj \
|
||||
$O\CabIn.obj \
|
||||
$O\CabInBuffer.obj \
|
||||
$O\LZXDecoder.obj \
|
||||
$O\LZXi86Converter.obj \
|
||||
$O\MSZipDecoder.obj \
|
||||
|
||||
COMMON_OBJS = \
|
||||
$O\Alloc.obj \
|
||||
@@ -32,6 +28,11 @@ WIN_OBJS = \
|
||||
$O\LSBFDecoder.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
COMPRESS_LZX_OBJS = \
|
||||
$O\LzxDecoder.obj \
|
||||
$O\Lzx86Converter.obj \
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
@@ -39,7 +40,11 @@ OBJS = \
|
||||
$(COMMON_OBJS) \
|
||||
$(WIN_OBJS) \
|
||||
$(7ZIP_COMMON_OBJS) \
|
||||
$(COMPRESS_LZX_OBJS) \
|
||||
$O\DeflateDecoder.obj \
|
||||
$O\QuantumDecoder.obj \
|
||||
$O\LZOutWindow.obj \
|
||||
$O\CopyCoder.obj \
|
||||
$O\resource.res
|
||||
|
||||
!include "../../../Build.mak"
|
||||
@@ -52,5 +57,14 @@ $(WIN_OBJS): ../../../Windows/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
$O\DeflateDecoder.obj: ../../Compress/Deflate/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
$O\QuantumDecoder.obj: ../../Compress/Quantum/$(*B).cpp
|
||||
$(COMPL)
|
||||
$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp
|
||||
$(COMPL)
|
||||
$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
|
||||
$(COMPL)
|
||||
|
||||
|
||||
337
7zip/Archive/Chm/Chm.dsp
Executable file
337
7zip/Archive/Chm/Chm.dsp
Executable file
@@ -0,0 +1,337 @@
|
||||
# Microsoft Developer Studio Project File - Name="Chm" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=Chm - 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 "Chm.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 "Chm.mak" CFG="Chm - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Chm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "Chm - 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)" == "Chm - 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 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_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\chm.dll" /opt:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "Chm - 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 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_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\chm.dll" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "Chm - Win32 Release"
|
||||
# Name "Chm - Win32 Debug"
|
||||
# Begin Group "Spec"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Archive.def
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\DllExports.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.cpp
|
||||
# ADD CPP /Yc"StdAfx.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\StdAfx.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Engine"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmHandler.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmHandler.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmHeader.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmHeader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmIn.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ChmIn.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\LimitedStreams.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\LimitedStreams.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
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Alloc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Alloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Buffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\IntToString.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 "Archive Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ItemNameUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\Common\ItemNameUtils.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
|
||||
# Begin Group "Lzx"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp
|
||||
|
||||
!IF "$(CFG)" == "Chm - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Chm - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\Lzx86Converter.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp
|
||||
|
||||
!IF "$(CFG)" == "Chm - Win32 Release"
|
||||
|
||||
# ADD CPP /O2
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
|
||||
!ELSEIF "$(CFG)" == "Chm - Win32 Debug"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzx\LzxDecoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Copy\CopyCoder.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Copy\CopyCoder.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
29
7zip/Archive/Chm/Chm.dsw
Executable file
29
7zip/Archive/Chm/Chm.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: "Chm"=.\Chm.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
729
7zip/Archive/Chm/ChmHandler.cpp
Executable file
729
7zip/Archive/Chm/ChmHandler.cpp
Executable file
@@ -0,0 +1,729 @@
|
||||
// Chm/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 "../../Common/LimitedStreams.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
#include "../../Common/ProgressUtils.h"
|
||||
|
||||
#include "../../Compress/Copy/CopyCoder.h"
|
||||
#include "../../Compress/Lzx/LzxDecoder.h"
|
||||
|
||||
#include "../Common/ItemNameUtils.h"
|
||||
|
||||
#include "ChmHandler.h"
|
||||
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NTime;
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
// #define _CHM_DETAILS
|
||||
|
||||
#ifdef _CHM_DETAILS
|
||||
|
||||
enum
|
||||
{
|
||||
kpidSection = kpidUserDefined,
|
||||
kpidOffset
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
STATPROPSTG kProperties[] =
|
||||
{
|
||||
{ NULL, kpidPath, VT_BSTR},
|
||||
// { NULL, kpidIsFolder, VT_BOOL},
|
||||
{ NULL, kpidSize, VT_UI8},
|
||||
{ NULL, kpidMethod, VT_BSTR},
|
||||
{ NULL, kpidBlock, VT_UI4}
|
||||
|
||||
#ifdef _CHM_DETAILS
|
||||
,
|
||||
{ L"Section", kpidSection, VT_UI4},
|
||||
{ L"Offset", kpidOffset, VT_UI4}
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
|
||||
|
||||
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;
|
||||
if (srcItem.lpwstrName == 0)
|
||||
*name = 0;
|
||||
else
|
||||
*name = ::SysAllocString(srcItem.lpwstrName);
|
||||
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;
|
||||
if (m_Database.NewFormat)
|
||||
{
|
||||
switch(propID)
|
||||
{
|
||||
case kpidSize:
|
||||
propVariant = (UInt64)m_Database.NewFormatString.Length();
|
||||
break;
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
int entryIndex;
|
||||
if (m_Database.LowLevel)
|
||||
entryIndex = index;
|
||||
else
|
||||
entryIndex = m_Database.Indices[index];
|
||||
const CItem &item = m_Database.Items[entryIndex];
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
{
|
||||
UString us;
|
||||
if (ConvertUTF8ToUnicode(item.Name, us))
|
||||
{
|
||||
if (!m_Database.LowLevel)
|
||||
{
|
||||
if (us.Length() > 1)
|
||||
if (us[0] == L'/')
|
||||
us.Delete(0);
|
||||
}
|
||||
propVariant = NItemName::GetOSName2(us);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kpidIsFolder:
|
||||
propVariant = item.IsDirectory();
|
||||
break;
|
||||
case kpidSize:
|
||||
propVariant = item.Size;
|
||||
break;
|
||||
case kpidMethod:
|
||||
{
|
||||
if (!item.IsDirectory())
|
||||
if (item.Section == 0)
|
||||
propVariant = L"Copy";
|
||||
else if (item.Section < m_Database.Sections.Size())
|
||||
propVariant = m_Database.Sections[(size_t)item.Section].GetMethodName();
|
||||
break;
|
||||
}
|
||||
case kpidBlock:
|
||||
if (m_Database.LowLevel)
|
||||
propVariant = item.Section;
|
||||
else if (item.Section != 0)
|
||||
propVariant = m_Database.GetFolder(index);
|
||||
break;
|
||||
|
||||
#ifdef _CHM_DETAILS
|
||||
|
||||
case kpidSection:
|
||||
propVariant = (UInt32)item.Section;
|
||||
break;
|
||||
case kpidOffset:
|
||||
propVariant = (UInt32)item.Offset;
|
||||
break;
|
||||
|
||||
#endif
|
||||
}
|
||||
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;
|
||||
CPropgressImp progressImp;
|
||||
progressImp.Init(openArchiveCallback);
|
||||
RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database));
|
||||
/*
|
||||
if (m_Database.LowLevel)
|
||||
return S_FALSE;
|
||||
*/
|
||||
m_Stream = inStream;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::Close()
|
||||
{
|
||||
m_Stream.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CChmFolderOutStream:
|
||||
public ISequentialOutStream,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
UInt64 m_FolderSize;
|
||||
UInt64 m_PosInFolder;
|
||||
UInt64 m_PosInSection;
|
||||
const CRecordVector<bool> *m_ExtractStatuses;
|
||||
int m_StartIndex;
|
||||
int m_CurrentIndex;
|
||||
int m_NumFiles;
|
||||
|
||||
private:
|
||||
const CFilesDatabase *m_Database;
|
||||
CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
|
||||
bool m_TestMode;
|
||||
|
||||
bool m_IsOk;
|
||||
bool m_FileIsOpen;
|
||||
UInt64 m_RemainFileSize;
|
||||
CMyComPtr<ISequentialOutStream> m_RealOutStream;
|
||||
|
||||
HRESULT OpenFile();
|
||||
HRESULT WriteEmptyFiles();
|
||||
public:
|
||||
void Init(
|
||||
const CFilesDatabase *database,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode);
|
||||
HRESULT FlushCorrupted();
|
||||
};
|
||||
|
||||
void CChmFolderOutStream::Init(
|
||||
const CFilesDatabase *database,
|
||||
IArchiveExtractCallback *extractCallback,
|
||||
bool testMode)
|
||||
{
|
||||
m_Database = database;
|
||||
m_ExtractCallback = extractCallback;
|
||||
m_TestMode = testMode;
|
||||
|
||||
m_CurrentIndex = 0;
|
||||
m_FileIsOpen = false;
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::OpenFile()
|
||||
{
|
||||
Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
|
||||
NExtract::NAskMode::kTest :
|
||||
NExtract::NAskMode::kExtract) :
|
||||
NExtract::NAskMode::kSkip;
|
||||
m_RealOutStream.Release();
|
||||
RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
|
||||
if (!m_RealOutStream && !m_TestMode)
|
||||
askMode = NArchive::NExtract::NAskMode::kSkip;
|
||||
return m_ExtractCallback->PrepareOperation(askMode);
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::WriteEmptyFiles()
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
return S_OK;
|
||||
for(;m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
|
||||
{
|
||||
UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
|
||||
if (fileSize != 0)
|
||||
return S_OK;
|
||||
HRESULT result = OpenFile();
|
||||
m_RealOutStream.Release();
|
||||
RINOK(result);
|
||||
RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// This is WritePart function
|
||||
HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
|
||||
{
|
||||
UInt32 realProcessed = 0;
|
||||
if (processedSize != NULL)
|
||||
*processedSize = 0;
|
||||
while(size != 0)
|
||||
{
|
||||
if (m_FileIsOpen)
|
||||
{
|
||||
UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));
|
||||
HRESULT res = S_OK;
|
||||
if (numBytesToWrite > 0)
|
||||
{
|
||||
if (!isOK)
|
||||
m_IsOk = false;
|
||||
if (m_RealOutStream)
|
||||
{
|
||||
UInt32 processedSizeLocal = 0;
|
||||
res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
|
||||
numBytesToWrite = processedSizeLocal;
|
||||
}
|
||||
}
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize != NULL)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_RemainFileSize -= numBytesToWrite;
|
||||
m_PosInSection += numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (m_RemainFileSize == 0)
|
||||
{
|
||||
m_RealOutStream.Release();
|
||||
RINOK(m_ExtractCallback->SetOperationResult(
|
||||
m_IsOk ?
|
||||
NArchive::NExtract::NOperationResult::kOK:
|
||||
NArchive::NExtract::NOperationResult::kDataError));
|
||||
m_FileIsOpen = false;
|
||||
}
|
||||
if (realProcessed > 0)
|
||||
break; // with this break this function works as write part
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_CurrentIndex >= m_NumFiles)
|
||||
return E_FAIL;
|
||||
int fullIndex = m_StartIndex + m_CurrentIndex;
|
||||
m_RemainFileSize = m_Database->GetFileSize(fullIndex);
|
||||
UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
|
||||
if (fileOffset < m_PosInSection)
|
||||
return E_FAIL;
|
||||
if (fileOffset > m_PosInSection)
|
||||
{
|
||||
UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));
|
||||
realProcessed += numBytesToWrite;
|
||||
if (processedSize != NULL)
|
||||
*processedSize = realProcessed;
|
||||
data = (const void *)((const Byte *)data + numBytesToWrite);
|
||||
size -= numBytesToWrite;
|
||||
m_PosInSection += numBytesToWrite;
|
||||
m_PosInFolder += numBytesToWrite;
|
||||
}
|
||||
if (fileOffset == m_PosInSection)
|
||||
{
|
||||
RINOK(OpenFile());
|
||||
m_FileIsOpen = true;
|
||||
m_CurrentIndex++;
|
||||
m_IsOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return WriteEmptyFiles();
|
||||
}
|
||||
|
||||
STDMETHODIMP CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write2(data, size, processedSize, true);
|
||||
}
|
||||
|
||||
HRESULT CChmFolderOutStream::FlushCorrupted()
|
||||
{
|
||||
const UInt32 kBufferSize = (1 << 10);
|
||||
Byte buffer[kBufferSize];
|
||||
for (int i = 0; i < kBufferSize; i++)
|
||||
buffer[i] = 0;
|
||||
while(m_PosInFolder < m_FolderSize)
|
||||
{
|
||||
UInt32 size = (UInt32)MyMin(m_FolderSize - m_PosInFolder, (UInt64)kBufferSize);
|
||||
UInt32 processedSizeLocal = 0;
|
||||
RINOK(Write2(buffer, size, &processedSizeLocal, false));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
bool allFilesMode = (numItems == UInt32(-1));
|
||||
|
||||
if (allFilesMode)
|
||||
numItems = m_Database.NewFormat ? 1:
|
||||
(m_Database.LowLevel ?
|
||||
m_Database.Items.Size():
|
||||
m_Database.Indices.Size());
|
||||
if(numItems == 0)
|
||||
return S_OK;
|
||||
bool testMode = (_aTestMode != 0);
|
||||
|
||||
UInt64 currentTotalSize = 0;
|
||||
|
||||
CMyComPtr<ICompressCoder> copyCoder;
|
||||
UInt32 i;
|
||||
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
||||
|
||||
if (m_Database.LowLevel)
|
||||
{
|
||||
UInt64 currentItemSize = 0;
|
||||
UInt64 totalSize = 0;
|
||||
if (m_Database.NewFormat)
|
||||
totalSize = m_Database.NewFormatString.Length();
|
||||
else
|
||||
for(i = 0; i < numItems; i++)
|
||||
totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
|
||||
extractCallback->SetTotal(totalSize);
|
||||
|
||||
for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
Int32 askMode;
|
||||
askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
|
||||
NArchive::NExtract::NAskMode::kExtract;
|
||||
Int32 index = allFilesMode ? i : indices[i];
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
|
||||
if (m_Database.NewFormat)
|
||||
{
|
||||
if (index != 0)
|
||||
return E_FAIL;
|
||||
if(!testMode && (!realOutStream))
|
||||
continue;
|
||||
if (!testMode)
|
||||
{
|
||||
UInt32 size = m_Database.NewFormatString.Length();
|
||||
RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size, 0));
|
||||
}
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
const CItem &item = m_Database.Items[index];
|
||||
|
||||
currentItemSize = item.Size;
|
||||
|
||||
if(!testMode && (!realOutStream))
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (item.Section != 0)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (testMode)
|
||||
{
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, item.Size);
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
localProgressSpec->Init(extractCallback, false);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
localCompressProgressSpec->Init(progress, ¤tTotalSize, ¤tTotalSize);
|
||||
|
||||
if(!copyCoder)
|
||||
copyCoder = new NCompress::CCopyCoder;
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UInt64 lastFolderIndex = ((UInt64)0 - 1);
|
||||
for(i = 0; i < numItems; i++)
|
||||
{
|
||||
UInt32 index = allFilesMode ? i : indices[i];
|
||||
int entryIndex = m_Database.Indices[index];
|
||||
const CItem &item = m_Database.Items[entryIndex];
|
||||
UInt64 sectionIndex = item.Section;
|
||||
if (item.IsDirectory() || item.Size == 0)
|
||||
continue;
|
||||
if (sectionIndex == 0)
|
||||
{
|
||||
currentTotalSize += item.Size;
|
||||
continue;
|
||||
}
|
||||
const CSectionInfo §ion = m_Database.Sections[(size_t)item.Section];
|
||||
if (section.IsLzx())
|
||||
{
|
||||
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
|
||||
UInt64 folderIndex = m_Database.GetFolder(index);
|
||||
if (lastFolderIndex == folderIndex)
|
||||
folderIndex++;
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
for (; folderIndex <= lastFolderIndex; folderIndex++)
|
||||
currentTotalSize += lzxInfo.GetFolderSize();
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(extractCallback->SetTotal(currentTotalSize));
|
||||
|
||||
NCompress::NLzx::CDecoder *lzxDecoderSpec = 0;
|
||||
CMyComPtr<ICompressCoder> lzxDecoder;
|
||||
CChmFolderOutStream *chmFolderOutStream = 0;
|
||||
CMyComPtr<ISequentialOutStream> outStream;
|
||||
|
||||
currentTotalSize = 0;
|
||||
|
||||
CRecordVector<bool> extractStatuses;
|
||||
for(i = 0; i < numItems;)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
||||
UInt32 index = allFilesMode ? i : indices[i];
|
||||
i++;
|
||||
int entryIndex = m_Database.Indices[index];
|
||||
const CItem &item = m_Database.Items[entryIndex];
|
||||
UInt64 sectionIndex = item.Section;
|
||||
Int32 askMode= testMode ?
|
||||
NArchive::NExtract::NAskMode::kTest :
|
||||
NArchive::NExtract::NAskMode::kExtract;
|
||||
if (item.IsDirectory())
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
continue;
|
||||
}
|
||||
|
||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
|
||||
localProgressSpec->Init(extractCallback, false);
|
||||
|
||||
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
|
||||
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
|
||||
localCompressProgressSpec->Init(progress, NULL, ¤tTotalSize);
|
||||
|
||||
if (item.Size == 0 || sectionIndex == 0)
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
if(!testMode && (!realOutStream))
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
if (!testMode && item.Size != 0)
|
||||
{
|
||||
RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, item.Size);
|
||||
if(!copyCoder)
|
||||
copyCoder = new NCompress::CCopyCoder;
|
||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
|
||||
}
|
||||
realOutStream.Release();
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||
currentTotalSize += item.Size;
|
||||
continue;
|
||||
}
|
||||
|
||||
const CSectionInfo §ion = m_Database.Sections[(size_t)sectionIndex];
|
||||
|
||||
if (!section.IsLzx())
|
||||
{
|
||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
||||
if(!testMode && (!realOutStream))
|
||||
continue;
|
||||
RINOK(extractCallback->PrepareOperation(askMode));
|
||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
|
||||
continue;
|
||||
}
|
||||
|
||||
const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
|
||||
|
||||
if (chmFolderOutStream == 0)
|
||||
{
|
||||
chmFolderOutStream = new CChmFolderOutStream;
|
||||
outStream = chmFolderOutStream;
|
||||
}
|
||||
|
||||
chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
|
||||
|
||||
if(lzxDecoderSpec == NULL)
|
||||
{
|
||||
lzxDecoderSpec = new NCompress::NLzx::CDecoder;
|
||||
lzxDecoder = lzxDecoderSpec;
|
||||
}
|
||||
|
||||
UInt64 folderIndex = m_Database.GetFolder(index);
|
||||
|
||||
UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
|
||||
UInt32 numDictBits = lzxInfo.GetNumDictBits();
|
||||
RINOK(lzxDecoderSpec->SetParams(numDictBits));
|
||||
|
||||
const CItem *lastItem = &item;
|
||||
extractStatuses.Clear();
|
||||
extractStatuses.Add(true);
|
||||
|
||||
for (;true; folderIndex++)
|
||||
{
|
||||
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
||||
|
||||
UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
|
||||
UInt64 finishPos = lastItem->Offset + lastItem->Size;
|
||||
UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
|
||||
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
UInt64 folderSize = lzxInfo.GetFolderSize();
|
||||
UInt64 unPackSize = folderSize;
|
||||
if (extractStatuses.IsEmpty())
|
||||
chmFolderOutStream->m_StartIndex = index + 1;
|
||||
else
|
||||
chmFolderOutStream->m_StartIndex = index;
|
||||
if (limitFolderIndex == folderIndex)
|
||||
{
|
||||
for(; i < numItems; i++)
|
||||
{
|
||||
UInt32 nextIndex = allFilesMode ? i : indices[i];
|
||||
int entryIndex = m_Database.Indices[nextIndex];
|
||||
const CItem &nextItem = m_Database.Items[entryIndex];
|
||||
if (nextItem.Section != sectionIndex)
|
||||
break;
|
||||
UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
|
||||
if (nextFolderIndex != folderIndex)
|
||||
break;
|
||||
for (index++; index < nextIndex; index++)
|
||||
extractStatuses.Add(false);
|
||||
extractStatuses.Add(true);
|
||||
index = nextIndex;
|
||||
lastItem = &nextItem;
|
||||
if (nextItem.Size != 0)
|
||||
finishPos = nextItem.Offset + nextItem.Size;
|
||||
lastFolderIndex = m_Database.GetLastFolder(index);
|
||||
}
|
||||
}
|
||||
unPackSize = MyMin(finishPos - startPos, unPackSize);
|
||||
|
||||
chmFolderOutStream->m_FolderSize = folderSize;
|
||||
chmFolderOutStream->m_PosInFolder = 0;
|
||||
chmFolderOutStream->m_PosInSection = startPos;
|
||||
chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
|
||||
chmFolderOutStream->m_NumFiles = extractStatuses.Size();
|
||||
chmFolderOutStream->m_CurrentIndex = 0;
|
||||
try
|
||||
{
|
||||
UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
|
||||
const CResetTable &rt = lzxInfo.ResetTable;
|
||||
UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
|
||||
for (UInt32 b = 0; b < numBlocks; b++)
|
||||
{
|
||||
UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
|
||||
RINOK(extractCallback->SetCompleted(&completedSize));
|
||||
UInt64 bCur = startBlock + b;
|
||||
if (bCur >= rt.ResetOffsets.Size())
|
||||
return E_FAIL;
|
||||
UInt64 startOffset = rt.ResetOffsets[(int)startBlock];
|
||||
UInt64 offset = rt.ResetOffsets[(int)bCur];
|
||||
UInt64 compressedSize;
|
||||
rt.GetCompressedSizeOfBlock(bCur, compressedSize);
|
||||
UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;
|
||||
if (rem > rt.BlockSize)
|
||||
rem = rt.BlockSize;
|
||||
const UInt64 *offsets = (const UInt64 *)&rt.ResetOffsets.Front();
|
||||
RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));
|
||||
streamSpec->Init(m_Stream, compressedSize);
|
||||
lzxDecoderSpec->SetKeepHistory(b > 0, (int)((offset - startOffset) & 1));
|
||||
RINOK(lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL));
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
RINOK(chmFolderOutStream->FlushCorrupted());
|
||||
}
|
||||
currentTotalSize += folderSize;
|
||||
if (folderIndex == lastFolderIndex)
|
||||
break;
|
||||
extractStatuses.Clear();
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
*numItems = m_Database.NewFormat ? 1:
|
||||
(m_Database.LowLevel ?
|
||||
m_Database.Items.Size():
|
||||
m_Database.Indices.Size());
|
||||
return S_OK;
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
}}
|
||||
46
7zip/Archive/Chm/ChmHandler.h
Executable file
46
7zip/Archive/Chm/ChmHandler.h
Executable file
@@ -0,0 +1,46 @@
|
||||
// ChmHandler.h
|
||||
|
||||
#ifndef __ARCHIVE_CHM_HANDLER_H
|
||||
#define __ARCHIVE_CHM_HANDLER_H
|
||||
|
||||
#include "Common/MyCom.h"
|
||||
#include "../IArchive.h"
|
||||
#include "ChmIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
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:
|
||||
CFilesDatabase m_Database;
|
||||
CMyComPtr<IInStream> m_Stream;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
24
7zip/Archive/Chm/ChmHeader.cpp
Executable file
24
7zip/Archive/Chm/ChmHeader.cpp
Executable file
@@ -0,0 +1,24 @@
|
||||
// Archive/Chm/Header.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ChmHeader.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NChm{
|
||||
namespace NHeader{
|
||||
|
||||
UInt32 kItsfSignature = 0x46535449 + 1;
|
||||
UInt32 kItolSignature = 0x4C4F5449 + 1;
|
||||
static class CSignatureInitializer
|
||||
{
|
||||
public:
|
||||
CSignatureInitializer()
|
||||
{
|
||||
kItsfSignature--;
|
||||
kItolSignature--;
|
||||
}
|
||||
}g_SignatureInitializer;
|
||||
|
||||
|
||||
}}}
|
||||
28
7zip/Archive/Chm/ChmHeader.h
Executable file
28
7zip/Archive/Chm/ChmHeader.h
Executable file
@@ -0,0 +1,28 @@
|
||||
// Archive/Chm/Header.h
|
||||
|
||||
#ifndef __ARCHIVE_CHM_HEADER_H
|
||||
#define __ARCHIVE_CHM_HEADER_H
|
||||
|
||||
#include "Common/Types.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
namespace NHeader{
|
||||
|
||||
const UInt32 kItspSignature = 0x50535449;
|
||||
const UInt32 kPmglSignature = 0x4C474D50;
|
||||
const UInt32 kLzxcSignature = 0x43585A4C;
|
||||
|
||||
const UInt32 kIfcmSignature = 0x4D434649;
|
||||
const UInt32 kAollSignature = 0x4C4C4F41;
|
||||
const UInt32 kCaolSignature = 0x4C4F4143;
|
||||
|
||||
extern UInt32 kItsfSignature;
|
||||
|
||||
extern UInt32 kItolSignature;
|
||||
const UInt32 kItlsSignature = 0x534C5449;
|
||||
UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; }
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
924
7zip/Archive/Chm/ChmIn.cpp
Executable file
924
7zip/Archive/Chm/ChmIn.cpp
Executable file
@@ -0,0 +1,924 @@
|
||||
// Archive/ChmIn.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/StringConvert.h"
|
||||
#include "Common/MyCom.h"
|
||||
#include "Common/UTFConvert.h"
|
||||
#include "Common/IntToString.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
#include "ChmIn.h"
|
||||
|
||||
namespace NArchive{
|
||||
namespace NChm{
|
||||
|
||||
// define CHM_LOW, if you want to see low level items
|
||||
// #define CHM_LOW
|
||||
|
||||
static const GUID kChmLzxGuid =
|
||||
{ 0x7FC28940, 0x9D31, 0x11D0, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };
|
||||
static const GUID kHelp2LzxGuid =
|
||||
{ 0x0A9007C6, 0x4076, 0x11D3, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };
|
||||
static const GUID kDesGuid =
|
||||
{ 0x67F6E4A2, 0x60BF, 0x11D3, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };
|
||||
|
||||
static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
|
||||
{
|
||||
if (g1.Data1 != g2.Data1 ||
|
||||
g1.Data2 != g2.Data2 ||
|
||||
g1.Data3 != g2.Data3)
|
||||
return false;
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (g1.Data4[i] != g2.Data4[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static char GetHex(Byte value)
|
||||
{
|
||||
return (value < 10) ? ('0' + value) : ('A' + (value - 10));
|
||||
}
|
||||
|
||||
static void PrintByte(Byte b, AString &s)
|
||||
{
|
||||
s += GetHex(b >> 4);
|
||||
s += GetHex(b & 0xF);
|
||||
}
|
||||
|
||||
static void PrintUInt16(UInt16 v, AString &s)
|
||||
{
|
||||
PrintByte((Byte)(v >> 8), s);
|
||||
PrintByte((Byte)v, s);
|
||||
}
|
||||
|
||||
static void PrintUInt32(UInt32 v, AString &s)
|
||||
{
|
||||
PrintUInt16((UInt16)(v >> 16), s);
|
||||
PrintUInt16((UInt16)v, s);
|
||||
}
|
||||
|
||||
AString CMethodInfo::GetGuidString() const
|
||||
{
|
||||
AString s;
|
||||
s += '{';
|
||||
PrintUInt32(Guid.Data1, s);
|
||||
s += '-';
|
||||
PrintUInt16(Guid.Data2, s);
|
||||
s += '-';
|
||||
PrintUInt16(Guid.Data3, s);
|
||||
s += '-';
|
||||
PrintByte(Guid.Data4[0], s);
|
||||
PrintByte(Guid.Data4[1], s);
|
||||
s += '-';
|
||||
for (int i = 2; i < 8; i++)
|
||||
PrintByte(Guid.Data4[i], s);
|
||||
s += '}';
|
||||
return s;
|
||||
}
|
||||
|
||||
bool CMethodInfo::IsLzx() const
|
||||
{
|
||||
if (AreGuidsEqual(Guid, kChmLzxGuid))
|
||||
return true;
|
||||
return AreGuidsEqual(Guid, kHelp2LzxGuid);
|
||||
}
|
||||
|
||||
bool CMethodInfo::IsDes() const
|
||||
{
|
||||
return AreGuidsEqual(Guid, kDesGuid);
|
||||
}
|
||||
|
||||
UString CMethodInfo::GetName() const
|
||||
{
|
||||
UString s;
|
||||
if (IsLzx())
|
||||
{
|
||||
s = L"LZX:";
|
||||
UInt32 numDictBits = LzxInfo.GetNumDictBits();
|
||||
wchar_t temp[32];
|
||||
ConvertUInt64ToString(numDictBits, temp);
|
||||
s += temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
AString s2;
|
||||
if (IsDes())
|
||||
s2 = "DES";
|
||||
else
|
||||
{
|
||||
s2 = GetGuidString();
|
||||
if (ControlData.GetCapacity() > 0)
|
||||
{
|
||||
s2 += ":";
|
||||
for (size_t i = 0; i < ControlData.GetCapacity(); i++)
|
||||
PrintByte(ControlData[i], s2);
|
||||
}
|
||||
}
|
||||
ConvertUTF8ToUnicode(s2, s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool CSectionInfo::IsLzx() const
|
||||
{
|
||||
if (Methods.Size() != 1)
|
||||
return false;
|
||||
return Methods[0].IsLzx();
|
||||
}
|
||||
|
||||
UString CSectionInfo::GetMethodName() const
|
||||
{
|
||||
UString s;
|
||||
if (!IsLzx())
|
||||
{
|
||||
UString temp;
|
||||
if (ConvertUTF8ToUnicode(Name, temp))
|
||||
s += temp;
|
||||
s += L": ";
|
||||
}
|
||||
for (int i = 0; i < Methods.Size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
s += L" ";
|
||||
s += Methods[i].GetName();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Byte CInArchive::ReadByte()
|
||||
{
|
||||
Byte b;
|
||||
if (!_inBuffer.ReadByte(b))
|
||||
throw 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
void CInArchive::Skeep(size_t size)
|
||||
{
|
||||
while (size-- != 0)
|
||||
ReadByte();
|
||||
}
|
||||
|
||||
void CInArchive::ReadBytes(Byte *data, UInt32 size)
|
||||
{
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
data[i] = ReadByte();
|
||||
}
|
||||
|
||||
UInt16 CInArchive::ReadUInt16()
|
||||
{
|
||||
UInt16 value = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
value |= ((UInt16)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
|
||||
UInt32 CInArchive::ReadUInt32()
|
||||
{
|
||||
UInt32 value = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
value |= ((UInt32)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
|
||||
UInt64 CInArchive::ReadUInt64()
|
||||
{
|
||||
UInt64 value = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
value |= ((UInt64)(ReadByte()) << (8 * i));
|
||||
return value;
|
||||
}
|
||||
|
||||
UInt64 CInArchive::ReadEncInt()
|
||||
{
|
||||
UInt64 val = 0;;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Byte b = ReadByte();
|
||||
val |= (b & 0x7F);
|
||||
if (b < 0x80)
|
||||
return val;
|
||||
val <<= 7;
|
||||
}
|
||||
throw 1;
|
||||
}
|
||||
|
||||
void CInArchive::ReadGUID(GUID &g)
|
||||
{
|
||||
g.Data1 = ReadUInt32();
|
||||
g.Data2 = ReadUInt16();
|
||||
g.Data3 = ReadUInt16();
|
||||
ReadBytes(g.Data4, 8);
|
||||
}
|
||||
|
||||
void CInArchive::ReadString(int size, AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
while(size-- != 0)
|
||||
{
|
||||
char c = (char)ReadByte();
|
||||
if (c == 0)
|
||||
{
|
||||
Skeep(size);
|
||||
return;
|
||||
}
|
||||
s += c;
|
||||
}
|
||||
}
|
||||
|
||||
void CInArchive::ReadUString(int size, UString &s)
|
||||
{
|
||||
s.Empty();
|
||||
while(size-- != 0)
|
||||
{
|
||||
wchar_t c = ReadUInt16();
|
||||
if (c == 0)
|
||||
{
|
||||
Skeep(2 * size);
|
||||
return;
|
||||
}
|
||||
s += c;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
|
||||
{
|
||||
RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));
|
||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
||||
CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
|
||||
streamSpec->Init(inStream, size);
|
||||
_inBuffer.SetStream(limitedStream);
|
||||
_inBuffer.Init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::ReadDirEntry(CDatabase &database)
|
||||
{
|
||||
CItem item;
|
||||
UInt64 nameLength = ReadEncInt();
|
||||
if (nameLength == 0 || nameLength >= 0x10000000)
|
||||
return S_FALSE;
|
||||
ReadString((int)nameLength, item.Name);
|
||||
item.Section = ReadEncInt();
|
||||
item.Offset = ReadEncInt();
|
||||
item.Size = ReadEncInt();
|
||||
database.Items.Add(item);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
||||
{
|
||||
UInt32 headerSize = ReadUInt32();
|
||||
if (headerSize != 0x60)
|
||||
return S_FALSE;
|
||||
UInt32 unknown1 = ReadUInt32();
|
||||
if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file
|
||||
return S_FALSE;
|
||||
UInt32 timeStamp = ReadUInt32();
|
||||
// Considered as a big-endian DWORD, it appears to contain seconds (MSB) and
|
||||
// fractional seconds (second byte).
|
||||
// The third and fourth bytes may contain even more fractional bits.
|
||||
// The 4 least significant bits in the last byte are constant.
|
||||
UInt32 lang = ReadUInt32();
|
||||
GUID g;
|
||||
ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
|
||||
const int kNumSections = 2;
|
||||
UInt64 sectionOffsets[kNumSections];
|
||||
UInt64 sectionSizes[kNumSections];
|
||||
int i;
|
||||
for (i = 0; i < kNumSections; i++)
|
||||
{
|
||||
sectionOffsets[i] = ReadUInt64();
|
||||
sectionSizes[i] = ReadUInt64();
|
||||
}
|
||||
// if (chmVersion == 3)
|
||||
database.ContentOffset = ReadUInt64();
|
||||
/*
|
||||
else
|
||||
database.ContentOffset = _startPosition + 0x58
|
||||
*/
|
||||
|
||||
/*
|
||||
// Section 0
|
||||
ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]);
|
||||
if (sectionSizes[0] != 0x18)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // unknown: 01FE
|
||||
ReadUInt32(); // unknown: 0
|
||||
UInt64 fileSize = ReadUInt64();
|
||||
ReadUInt32(); // unknown: 0
|
||||
ReadUInt32(); // unknown: 0
|
||||
*/
|
||||
|
||||
// Section 1: The Directory Listing
|
||||
ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]);
|
||||
if (ReadUInt32() != NHeader::kItspSignature)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 1) // version
|
||||
return S_FALSE;
|
||||
UInt32 dirHeaderSize = ReadUInt32();
|
||||
ReadUInt32(); // 0x0A (unknown)
|
||||
UInt32 dirChunkSize = ReadUInt32(); // $1000
|
||||
if (dirChunkSize < 32)
|
||||
return S_FALSE;
|
||||
UInt32 density = ReadUInt32(); // "Density" of quickref section, usually 2.
|
||||
UInt32 depth = ReadUInt32(); // Depth of the index tree: 1 there is no index,
|
||||
// 2 if there is one level of PMGI chunks.
|
||||
|
||||
UInt32 chunkNumber = ReadUInt32(); // Chunk number of root index chunk, -1 if there is none
|
||||
// (though at least one file has 0 despite there being no
|
||||
// index chunk, probably a bug.)
|
||||
UInt32 firstPmglChunkNumber = ReadUInt32(); // Chunk number of first PMGL (listing) chunk
|
||||
UInt32 lastPmglChunkNumber = ReadUInt32(); // Chunk number of last PMGL (listing) chunk
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total)
|
||||
UInt32 windowsLangId = ReadUInt32();
|
||||
ReadGUID(g); // {5D02926A-212E-11D0-9DF9-00A0C922E6EC}
|
||||
ReadUInt32(); // 0x54 (This is the length again)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
|
||||
for (UInt32 ci = 0; ci < numDirChunks; ci++)
|
||||
{
|
||||
UInt64 chunkPos = _inBuffer.GetProcessedSize();
|
||||
if (ReadUInt32() == NHeader::kPmglSignature)
|
||||
{
|
||||
// The quickref area is written backwards from the end of the chunk.
|
||||
// One quickref entry exists for every n entries in the file, where n
|
||||
// is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.
|
||||
|
||||
UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk
|
||||
if (quickrefLength > dirChunkSize || quickrefLength < 2)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // Always 0
|
||||
ReadUInt32(); // Chunk number of previous listing chunk when reading
|
||||
// directory in sequence (-1 if this is the first listing chunk)
|
||||
ReadUInt32(); // Chunk number of next listing chunk when reading
|
||||
// directory in sequence (-1 if this is the last listing chunk)
|
||||
int numItems = 0;
|
||||
while (true)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
UInt32 offsetLimit = dirChunkSize - quickrefLength;
|
||||
if (offset > offsetLimit)
|
||||
return S_FALSE;
|
||||
if (offset == offsetLimit)
|
||||
break;
|
||||
RINOK(ReadDirEntry(database));
|
||||
numItems++;
|
||||
}
|
||||
Skeep(quickrefLength - 2);
|
||||
if (ReadUInt16() != numItems)
|
||||
return S_FALSE;
|
||||
}
|
||||
else
|
||||
Skeep(dirChunkSize - 4);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
||||
{
|
||||
if (ReadUInt32() != 1) // version
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x28) // Location of header section table
|
||||
return S_FALSE;
|
||||
UInt32 numHeaderSections = ReadUInt32();
|
||||
const int kNumHeaderSectionsMax = 5;
|
||||
if (numHeaderSections != kNumHeaderSectionsMax)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // Length of post-header table
|
||||
GUID g;
|
||||
ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754}
|
||||
|
||||
// header section table
|
||||
UInt64 sectionOffsets[kNumHeaderSectionsMax];
|
||||
UInt64 sectionSizes[kNumHeaderSectionsMax];
|
||||
UInt32 i;
|
||||
for (i = 0; i < numHeaderSections; i++)
|
||||
{
|
||||
sectionOffsets[i] = ReadUInt64();
|
||||
sectionSizes[i] = ReadUInt64();
|
||||
}
|
||||
|
||||
// Post-Header
|
||||
ReadUInt32(); // 2
|
||||
ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header)
|
||||
// ----- Directory information
|
||||
ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1
|
||||
ReadUInt64(); // Chunk number of first AOLL chunk in directory
|
||||
ReadUInt64(); // Chunk number of last AOLL chunk in directory
|
||||
ReadUInt64(); // 0 (unknown)
|
||||
ReadUInt32(); // $2000 (Directory chunk size of directory)
|
||||
ReadUInt32(); // Quickref density for main directory, usually 2
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
ReadUInt32(); // Depth of main directory index tree
|
||||
// 1 there is no index, 2 if there is one level of AOLI chunks.
|
||||
ReadUInt64(); // 0 (unknown)
|
||||
UInt64 numDirEntries = ReadUInt64(); // Number of directory entries
|
||||
// ----- Directory Index Information
|
||||
ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index)
|
||||
ReadUInt64(); // Chunk number of first AOLL chunk in directory index
|
||||
ReadUInt64(); // Chunk number of last AOLL chunk in directory index
|
||||
ReadUInt64(); // 0 (unknown)
|
||||
ReadUInt32(); // $200 (Directory chunk size of directory index)
|
||||
ReadUInt32(); // Quickref density for directory index, usually 2
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
ReadUInt32(); // Depth of directory index index tree.
|
||||
ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0.
|
||||
ReadUInt64(); // Number of directory index entries (same as number of AOLL
|
||||
// chunks in main directory)
|
||||
|
||||
// (The obvious guess for the following two fields, which recur in a number
|
||||
// of places, is they are maximum sizes for the directory and directory index.
|
||||
// However, I have seen no direct evidence that this is the case.)
|
||||
|
||||
ReadUInt32(); // $100000 (Same as field following chunk size in directory)
|
||||
ReadUInt32(); // $20000 (Same as field following chunk size in directory index)
|
||||
|
||||
ReadUInt64(); // 0 (unknown)
|
||||
if (ReadUInt32() != NHeader::kCaolSignature)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 2) // (Most likely a version number)
|
||||
return S_FALSE;
|
||||
UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section)
|
||||
if (caolLength >= 0x2C)
|
||||
{
|
||||
UInt32 c7 = ReadUInt16(); // Unknown. Remains the same when identical files are built.
|
||||
// Does not appear to be a checksum. Many files have
|
||||
// 'HH' (HTML Help?) here, indicating this may be a compiler ID
|
||||
// field. But at least one ITOL/ITLS compiler does not set this
|
||||
// field to a constant value.
|
||||
ReadUInt16(); // 0 (Unknown. Possibly part of 00A4 field)
|
||||
ReadUInt32(); // Unknown. Two values have been seen -- $43ED, and 0.
|
||||
ReadUInt32(); // $2000 (Directory chunk size of directory)
|
||||
ReadUInt32(); // $200 (Directory chunk size of directory index)
|
||||
ReadUInt32(); // $100000 (Same as field following chunk size in directory)
|
||||
ReadUInt32(); // $20000 (Same as field following chunk size in directory index)
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
ReadUInt32(); // 0 (Unknown)
|
||||
if (caolLength == 0x2C)
|
||||
{
|
||||
database.ContentOffset = 0;
|
||||
database.NewFormat = true;
|
||||
}
|
||||
else if (caolLength == 0x50)
|
||||
{
|
||||
ReadUInt32(); // 0 (Unknown)
|
||||
if (ReadUInt32() != NHeader::kItsfSignature)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x20) // $20 (length of ITSF)
|
||||
return S_FALSE;
|
||||
UInt32 unknown = ReadUInt32();
|
||||
if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;
|
||||
return S_FALSE;
|
||||
database.ContentOffset = _startPosition + ReadUInt64();
|
||||
UInt32 timeStamp = ReadUInt32();
|
||||
// A timestamp of some sort.
|
||||
// Considered as a big-endian DWORD, it appears to contain
|
||||
// seconds (MSB) and fractional seconds (second byte).
|
||||
// The third and fourth bytes may contain even more fractional
|
||||
// bits. The 4 least significant bits in the last byte are constant.
|
||||
UInt32 lang = ReadUInt32(); // BE?
|
||||
}
|
||||
else
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// Section 0
|
||||
ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]);
|
||||
if (sectionSizes[0] != 0x18)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // unknown: 01FE
|
||||
ReadUInt32(); // unknown: 0
|
||||
UInt64 fileSize = ReadUInt64();
|
||||
ReadUInt32(); // unknown: 0
|
||||
ReadUInt32(); // unknown: 0
|
||||
*/
|
||||
|
||||
// Section 1: The Directory Listing
|
||||
ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]);
|
||||
if (ReadUInt32() != NHeader::kIfcmSignature)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 1) // (probably a version number)
|
||||
return S_FALSE;
|
||||
UInt32 dirChunkSize = ReadUInt32(); // $2000
|
||||
if (dirChunkSize < 64)
|
||||
return S_FALSE;
|
||||
ReadUInt32(); // $100000 (unknown)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
ReadUInt32(); // -1 (unknown)
|
||||
UInt32 numDirChunks = ReadUInt32();
|
||||
ReadUInt32(); // 0 (unknown, probably high word of above)
|
||||
|
||||
for (UInt32 ci = 0; ci < numDirChunks; ci++)
|
||||
{
|
||||
UInt64 chunkPos = _inBuffer.GetProcessedSize();
|
||||
if (ReadUInt32() == NHeader::kAollSignature)
|
||||
{
|
||||
UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk
|
||||
if (quickrefLength > dirChunkSize || quickrefLength < 2)
|
||||
return S_FALSE;
|
||||
ReadUInt64(); // Directory chunk number
|
||||
// This must match physical position in file, that is
|
||||
// the chunk size times the chunk number must be the
|
||||
// offset from the end of the directory header.
|
||||
ReadUInt64(); // Chunk number of previous listing chunk when reading
|
||||
// directory in sequence (-1 if first listing chunk)
|
||||
ReadUInt64(); // Chunk number of next listing chunk when reading
|
||||
// directory in sequence (-1 if last listing chunk)
|
||||
ReadUInt64(); // Number of first listing entry in this chunk
|
||||
ReadUInt32(); // 1 (unknown -- other values have also been seen here)
|
||||
ReadUInt32(); // 0 (unknown)
|
||||
|
||||
int numItems = 0;
|
||||
while (true)
|
||||
{
|
||||
UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
|
||||
UInt32 offsetLimit = dirChunkSize - quickrefLength;
|
||||
if (offset > offsetLimit)
|
||||
return S_FALSE;
|
||||
if (offset == offsetLimit)
|
||||
break;
|
||||
if (database.NewFormat)
|
||||
{
|
||||
UInt16 nameLength = ReadUInt16();
|
||||
if (nameLength == 0)
|
||||
return S_FALSE;
|
||||
UString name;
|
||||
ReadUString((int)nameLength, name);
|
||||
AString s;
|
||||
ConvertUnicodeToUTF8(name, s);
|
||||
Byte b = ReadByte();
|
||||
s += ' ';
|
||||
PrintByte(b, s);
|
||||
s += ' ';
|
||||
UInt64 len = ReadEncInt();
|
||||
// then number of items ?
|
||||
// then length ?
|
||||
// then some data (binary encoding?)
|
||||
while (len-- != 0)
|
||||
{
|
||||
b = ReadByte();
|
||||
PrintByte(b, s);
|
||||
}
|
||||
database.NewFormatString += s;
|
||||
database.NewFormatString += "\r\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(ReadDirEntry(database));
|
||||
}
|
||||
numItems++;
|
||||
}
|
||||
Skeep(quickrefLength - 2);
|
||||
if (ReadUInt16() != numItems)
|
||||
return S_FALSE;
|
||||
if (numItems > numDirEntries)
|
||||
return S_FALSE;
|
||||
numDirEntries -= numItems;
|
||||
}
|
||||
else
|
||||
Skeep(dirChunkSize - 4);
|
||||
}
|
||||
return numDirEntries == 0 ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name)
|
||||
{
|
||||
int index = database.FindItem(name);
|
||||
if (index < 0)
|
||||
return S_FALSE;
|
||||
const CItem &item = database.Items[index];
|
||||
_chunkSize = item.Size;
|
||||
return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size);
|
||||
}
|
||||
|
||||
|
||||
#define DATA_SPACE "::DataSpace/"
|
||||
static const char *kNameList = DATA_SPACE "NameList";
|
||||
static const char *kStorage = DATA_SPACE "Storage/";
|
||||
static const char *kContent = "Content";
|
||||
static const char *kControlData = "ControlData";
|
||||
static const char *kSpanInfo = "SpanInfo";
|
||||
static const char *kTransform = "Transform/";
|
||||
static const char *kResetTable = "/InstanceData/ResetTable";
|
||||
static const char *kTransformList = "List";
|
||||
|
||||
static AString GetSectionPrefix(const AString &name)
|
||||
{
|
||||
return AString(kStorage) + name + AString("/");
|
||||
}
|
||||
|
||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||
|
||||
static int CompareFiles(const int *p1, const int *p2, void *param)
|
||||
{
|
||||
const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
|
||||
const CItem &item1 = items[*p1];
|
||||
const CItem &item2 = items[*p2];
|
||||
bool isDir1 = item1.IsDirectory();
|
||||
bool isDir2 = item2.IsDirectory();
|
||||
if (isDir1 && !isDir2)
|
||||
return -1;
|
||||
if (isDir2)
|
||||
{
|
||||
if (isDir1)
|
||||
return MyCompare(*p1, *p2);
|
||||
return 1;
|
||||
}
|
||||
RINOZ(MyCompare(item1.Section, item2.Section));
|
||||
RINOZ(MyCompare(item1.Offset, item2.Offset));
|
||||
RINOZ(MyCompare(item1.Size, item2.Size));
|
||||
return MyCompare(*p1, *p2);
|
||||
}
|
||||
|
||||
void CFilesDatabase::SetIndices()
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
const CItem &item = Items[i];
|
||||
if (item.IsUserItem() && item.Name.Length() != 1)
|
||||
Indices.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
void CFilesDatabase::Sort()
|
||||
{
|
||||
Indices.Sort(CompareFiles, (void *)&Items);
|
||||
}
|
||||
|
||||
bool CFilesDatabase::Check()
|
||||
{
|
||||
UInt64 maxPos = 0;
|
||||
UInt64 prevSection = 0;
|
||||
for(int i = 0; i < Indices.Size(); i++)
|
||||
{
|
||||
const CItem &item = Items[Indices[i]];
|
||||
if (item.Section == 0 || item.IsDirectory())
|
||||
continue;
|
||||
if (item.Section != prevSection)
|
||||
{
|
||||
prevSection = item.Section;
|
||||
maxPos = 0;
|
||||
continue;
|
||||
}
|
||||
if (item.Offset < maxPos)
|
||||
return false;
|
||||
maxPos = item.Offset + item.Size;
|
||||
if (maxPos < item.Offset)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
|
||||
{
|
||||
{
|
||||
// The NameList file
|
||||
RINOK(DecompressStream(inStream, database, kNameList));
|
||||
UInt16 length = ReadUInt16();
|
||||
UInt16 numSections = ReadUInt16();
|
||||
for (int i = 0; i < numSections; i++)
|
||||
{
|
||||
CSectionInfo section;
|
||||
UInt16 nameLength = ReadUInt16();
|
||||
UString name;
|
||||
ReadUString(nameLength, name);
|
||||
if (ReadUInt16() != 0)
|
||||
return S_FALSE;
|
||||
if (!ConvertUnicodeToUTF8(name, section.Name))
|
||||
return S_FALSE;
|
||||
database.Sections.Add(section);
|
||||
}
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 1; i < database.Sections.Size(); i++)
|
||||
{
|
||||
CSectionInfo §ion = database.Sections[i];
|
||||
AString sectionPrefix = GetSectionPrefix(section.Name);
|
||||
{
|
||||
// Content
|
||||
int index = database.FindItem(sectionPrefix + kContent);
|
||||
if (index < 0)
|
||||
return S_FALSE;
|
||||
const CItem &item = database.Items[index];
|
||||
section.Offset = item.Offset;
|
||||
section.CompressedSize = item.Size;
|
||||
}
|
||||
AString transformPrefix = sectionPrefix + kTransform;
|
||||
if (database.Help2Format)
|
||||
{
|
||||
// Transform List
|
||||
RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));
|
||||
if ((_chunkSize & 0xF) != 0)
|
||||
return S_FALSE;
|
||||
int numGuids = (int)(_chunkSize / 0x10);
|
||||
if (numGuids < 1)
|
||||
return S_FALSE;
|
||||
for (int i = 0; i < numGuids; i++)
|
||||
{
|
||||
CMethodInfo method;
|
||||
ReadGUID(method.Guid);
|
||||
section.Methods.Add(method);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CMethodInfo method;
|
||||
method.Guid = kChmLzxGuid;
|
||||
section.Methods.Add(method);
|
||||
}
|
||||
|
||||
{
|
||||
// Control Data
|
||||
RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData));
|
||||
for (int mi = 0; mi < section.Methods.Size(); mi++)
|
||||
{
|
||||
CMethodInfo &method = section.Methods[mi];
|
||||
UInt32 numDWORDS = ReadUInt32();
|
||||
if (method.IsLzx())
|
||||
{
|
||||
if (numDWORDS < 5)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != NHeader::kLzxcSignature)
|
||||
return S_FALSE;
|
||||
CLzxInfo &li = method.LzxInfo;
|
||||
li.Version = ReadUInt32();
|
||||
if (li.Version != 2 && li.Version != 3)
|
||||
return S_FALSE;
|
||||
li.ResetInterval = ReadUInt32();
|
||||
li.WindowSize = ReadUInt32();
|
||||
li.CacheSize = ReadUInt32();
|
||||
if (li.ResetInterval != 2 && li.ResetInterval != 4)
|
||||
return S_FALSE;
|
||||
if (li.WindowSize != 2 && li.WindowSize != 4)
|
||||
return S_FALSE;
|
||||
numDWORDS -= 5;
|
||||
while (numDWORDS-- != 0)
|
||||
ReadUInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 numBytes = numDWORDS * 4;
|
||||
method.ControlData.SetCapacity(numBytes);
|
||||
ReadBytes(method.ControlData, numBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// SpanInfo
|
||||
RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo));
|
||||
section.UncompressedSize = ReadUInt64();
|
||||
}
|
||||
|
||||
// read ResetTable for LZX
|
||||
for (int mi = 0; mi < section.Methods.Size(); mi++)
|
||||
{
|
||||
CMethodInfo &method = section.Methods[mi];
|
||||
if (method.IsLzx())
|
||||
{
|
||||
// ResetTable;
|
||||
RINOK(DecompressStream(inStream, database, transformPrefix +
|
||||
method.GetGuidString() + kResetTable));
|
||||
CResetTable &rt = method.LzxInfo.ResetTable;
|
||||
if (_chunkSize < 4)
|
||||
{
|
||||
if (_chunkSize != 0)
|
||||
return S_FALSE;
|
||||
// ResetTable is empty in .chw files
|
||||
if (section.UncompressedSize != 0)
|
||||
return S_FALSE;
|
||||
rt.UncompressedSize = 0;
|
||||
rt.CompressedSize = 0;
|
||||
rt.BlockSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number)
|
||||
if (ver != 2 && ver != 3)
|
||||
return S_FALSE;
|
||||
UInt32 numEntries = ReadUInt32();
|
||||
if (ReadUInt32() != 8) // Size of table entry (bytes)
|
||||
return S_FALSE;
|
||||
if (ReadUInt32() != 0x28) // Length of table header
|
||||
return S_FALSE;
|
||||
rt.UncompressedSize = ReadUInt64();
|
||||
rt.CompressedSize = ReadUInt64();
|
||||
rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below
|
||||
if (rt.BlockSize != 0x8000)
|
||||
return S_FALSE;
|
||||
rt.ResetOffsets.Reserve(numEntries);
|
||||
for (UInt32 i = 0; i < numEntries; i++)
|
||||
rt.ResetOffsets.Add(ReadUInt64());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
database.SetIndices();
|
||||
database.Sort();
|
||||
return database.Check() ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open2(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CFilesDatabase &database)
|
||||
{
|
||||
database.Clear();
|
||||
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
|
||||
|
||||
database.Help2Format = false;
|
||||
const UInt32 chmVersion = 3;
|
||||
{
|
||||
if (!_inBuffer.Create(1 << 14))
|
||||
return E_OUTOFMEMORY;
|
||||
_inBuffer.SetStream(inStream);
|
||||
_inBuffer.Init();
|
||||
UInt64 value = 0;
|
||||
const int kSignatureSize = 8;
|
||||
UInt64 hxsSignature = NHeader::GetHxsSignature();
|
||||
UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature;
|
||||
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 == chmSignature)
|
||||
break;
|
||||
if (value == hxsSignature)
|
||||
{
|
||||
database.Help2Format = true;
|
||||
break;
|
||||
}
|
||||
if (searchHeaderSizeLimit != NULL)
|
||||
if (_inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit))
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
_startPosition += _inBuffer.GetProcessedSize() - kSignatureSize;
|
||||
}
|
||||
|
||||
if (database.Help2Format)
|
||||
{
|
||||
RINOK(OpenHelp2(inStream, database));
|
||||
if (database.NewFormat)
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(OpenChm(inStream, database));
|
||||
}
|
||||
|
||||
#ifndef CHM_LOW
|
||||
try
|
||||
{
|
||||
HRESULT res = OpenHighLevel(inStream, database);
|
||||
if (res == S_FALSE)
|
||||
{
|
||||
database.HighLevelClear();
|
||||
return S_OK;
|
||||
}
|
||||
RINOK(res);
|
||||
database.LowLevel = false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CInArchive::Open(IInStream *inStream,
|
||||
const UInt64 *searchHeaderSizeLimit,
|
||||
CFilesDatabase &database)
|
||||
{
|
||||
try
|
||||
{
|
||||
HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);
|
||||
_inBuffer.ReleaseStream();
|
||||
return res;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
_inBuffer.ReleaseStream();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
242
7zip/Archive/Chm/ChmIn.h
Executable file
242
7zip/Archive/Chm/ChmIn.h
Executable file
@@ -0,0 +1,242 @@
|
||||
// Archive/ChmIn.h
|
||||
|
||||
#ifndef __ARCHIVE_CHM_IN_H
|
||||
#define __ARCHIVE_CHM_IN_H
|
||||
|
||||
#include "Common/String.h"
|
||||
#include "Common/Buffer.h"
|
||||
#include "../../IStream.h"
|
||||
#include "../../Common/InBuffer.h"
|
||||
#include "ChmHeader.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NChm {
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UInt64 Section;
|
||||
UInt64 Offset;
|
||||
UInt64 Size;
|
||||
AString Name;
|
||||
|
||||
bool IsFormatRelatedItem() const
|
||||
{
|
||||
if (Name.Length() < 2)
|
||||
return false;
|
||||
return Name[0] == ':' && Name[1] == ':';
|
||||
}
|
||||
|
||||
bool IsUserItem() const
|
||||
{
|
||||
if (Name.Length() < 2)
|
||||
return false;
|
||||
return Name[0] == '/';
|
||||
}
|
||||
|
||||
bool IsDirectory() const
|
||||
{
|
||||
if (Name.Length() == 0)
|
||||
return false;
|
||||
return (Name[Name.Length() - 1] == '/');
|
||||
}
|
||||
};
|
||||
|
||||
struct CDatabase
|
||||
{
|
||||
UInt64 ContentOffset;
|
||||
CObjectVector<CItem> Items;
|
||||
AString NewFormatString;
|
||||
bool Help2Format;
|
||||
bool NewFormat;
|
||||
|
||||
int FindItem(const AString &name) const
|
||||
{
|
||||
for (int i = 0; i < Items.Size(); i++)
|
||||
if (Items[i].Name == name)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
NewFormat = false;
|
||||
NewFormatString.Empty();
|
||||
Help2Format = false;
|
||||
Items.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct CResetTable
|
||||
{
|
||||
UInt64 UncompressedSize;
|
||||
UInt64 CompressedSize;
|
||||
UInt64 BlockSize;
|
||||
CRecordVector<UInt64> ResetOffsets;
|
||||
bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
|
||||
{
|
||||
if (blockIndex >= ResetOffsets.Size())
|
||||
return false;
|
||||
UInt64 startPos = ResetOffsets[(size_t)blockIndex];
|
||||
if (blockIndex + numBlocks >= ResetOffsets.Size())
|
||||
size = CompressedSize - startPos;
|
||||
else
|
||||
size = ResetOffsets[(size_t)blockIndex + numBlocks] - startPos;
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
|
||||
{
|
||||
return GetCompressedSizeOfBlocks(blockIndex, 1, size);
|
||||
}
|
||||
UInt64 GetNumBlocks(UInt64 size) const
|
||||
{
|
||||
return (size + BlockSize - 1) / BlockSize;
|
||||
}
|
||||
};
|
||||
|
||||
struct CLzxInfo
|
||||
{
|
||||
UInt32 Version;
|
||||
UInt32 ResetInterval;
|
||||
UInt32 WindowSize;
|
||||
UInt32 CacheSize;
|
||||
CResetTable ResetTable;
|
||||
|
||||
UInt32 GetNumDictBits() const
|
||||
{
|
||||
if (Version == 2 || Version == 3)
|
||||
{
|
||||
for (int i = 0; i <= 31; i++)
|
||||
if (((UInt32)1 << i) >= WindowSize)
|
||||
return 15 + i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; };
|
||||
UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); };
|
||||
UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); };
|
||||
UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; };
|
||||
bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
|
||||
{
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
if (blockIndex >= ResetTable.ResetOffsets.Size())
|
||||
return false;
|
||||
offset = ResetTable.ResetOffsets[(size_t)blockIndex];
|
||||
return true;
|
||||
}
|
||||
bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
|
||||
{
|
||||
UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
|
||||
return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size);
|
||||
}
|
||||
};
|
||||
|
||||
struct CMethodInfo
|
||||
{
|
||||
GUID Guid;
|
||||
CByteBuffer ControlData;
|
||||
CLzxInfo LzxInfo;
|
||||
bool IsLzx() const;
|
||||
bool IsDes() const;
|
||||
AString GetGuidString() const;
|
||||
UString GetName() const;
|
||||
};
|
||||
|
||||
struct CSectionInfo
|
||||
{
|
||||
UInt64 Offset;
|
||||
UInt64 CompressedSize;
|
||||
UInt64 UncompressedSize;
|
||||
|
||||
AString Name;
|
||||
CObjectVector<CMethodInfo> Methods;
|
||||
|
||||
bool IsLzx() const;
|
||||
UString GetMethodName() const;
|
||||
};
|
||||
|
||||
class CFilesDatabase: public CDatabase
|
||||
{
|
||||
public:
|
||||
bool LowLevel;
|
||||
CRecordVector<int> Indices;
|
||||
CObjectVector<CSectionInfo> Sections;
|
||||
|
||||
UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; }
|
||||
UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; }
|
||||
|
||||
UInt64 GetFolder(int fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
const CSectionInfo §ion = Sections[(size_t)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt64 GetLastFolder(int fileIndex) const
|
||||
{
|
||||
const CItem &item = Items[Indices[fileIndex]];
|
||||
const CSectionInfo §ion = Sections[(size_t)item.Section];
|
||||
if (section.IsLzx())
|
||||
return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HighLevelClear()
|
||||
{
|
||||
LowLevel = true;
|
||||
Indices.Clear();
|
||||
Sections.Clear();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
CDatabase::Clear();
|
||||
HighLevelClear();
|
||||
}
|
||||
void SetIndices();
|
||||
void Sort();
|
||||
bool Check();
|
||||
};
|
||||
|
||||
class CProgressVirt
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;
|
||||
STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
|
||||
};
|
||||
|
||||
class CInArchive
|
||||
{
|
||||
UInt64 _startPosition;
|
||||
::CInBuffer _inBuffer;
|
||||
UInt64 _chunkSize;
|
||||
|
||||
Byte ReadByte();
|
||||
void ReadBytes(Byte *data, UInt32 size);
|
||||
void Skeep(size_t size);
|
||||
UInt16 ReadUInt16();
|
||||
UInt32 ReadUInt32();
|
||||
UInt64 ReadUInt64();
|
||||
UInt64 ReadEncInt();
|
||||
void ReadString(int size, AString &s);
|
||||
void ReadUString(int size, UString &s);
|
||||
void ReadGUID(GUID &g);
|
||||
|
||||
HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
|
||||
|
||||
HRESULT ReadDirEntry(CDatabase &database);
|
||||
HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);
|
||||
|
||||
public:
|
||||
HRESULT OpenChm(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);
|
||||
HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);
|
||||
HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
|
||||
HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
77
7zip/Archive/Chm/DllExports.cpp
Executable file
77
7zip/Archive/Chm/DllExports.cpp
Executable file
@@ -0,0 +1,77 @@
|
||||
// DLLExports.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Common/MyInitGuid.h"
|
||||
#include "Common/ComTry.h"
|
||||
#include "Windows/PropVariant.h"
|
||||
#include "ChmHandler.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110E90000}
|
||||
DEFINE_GUID(CLSID_CChmHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 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_CChmHandler)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
if (*interfaceID != IID_IInArchive)
|
||||
return E_NOINTERFACE;
|
||||
CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NChm::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"Chm";
|
||||
break;
|
||||
case NArchive::kClassID:
|
||||
{
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(
|
||||
(const char *)&CLSID_CChmHandler, sizeof(GUID))) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
case NArchive::kExtension:
|
||||
propVariant = L"chm chi chq chw hxs hxi hxr hxq hxw lit";
|
||||
break;
|
||||
case NArchive::kUpdate:
|
||||
propVariant = false;
|
||||
break;
|
||||
case NArchive::kKeepName:
|
||||
propVariant = false;
|
||||
break;
|
||||
case NArchive::kStartSignature:
|
||||
{
|
||||
const char sig[] = { 'I', 'T', 'S', 'F' };
|
||||
if ((value->bstrVal = ::SysAllocStringByteLen(sig, 4)) != 0)
|
||||
value->vt = VT_BSTR;
|
||||
return S_OK;
|
||||
}
|
||||
case NArchive::kAssociate:
|
||||
{
|
||||
propVariant = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
propVariant.Detach(value);
|
||||
return S_OK;
|
||||
}
|
||||
3
7zip/Archive/Chm/StdAfx.cpp
Executable file
3
7zip/Archive/Chm/StdAfx.cpp
Executable file
@@ -0,0 +1,3 @@
|
||||
// StdAfx.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
8
7zip/Archive/Chm/StdAfx.h
Executable file
8
7zip/Archive/Chm/StdAfx.h
Executable file
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../../../Common/MyWindows.h"
|
||||
|
||||
#endif
|
||||
68
7zip/Archive/Chm/makefile
Executable file
68
7zip/Archive/Chm/makefile
Executable file
@@ -0,0 +1,68 @@
|
||||
PROG = chm.dll
|
||||
DEF_FILE = ../Archive.def
|
||||
CFLAGS = $(CFLAGS) -I ../../../
|
||||
LIBS = $(LIBS) oleaut32.lib user32.lib
|
||||
|
||||
CHM_OBJS = \
|
||||
$O\DllExports.obj \
|
||||
$O\ChmHandler.obj \
|
||||
$O\ChmHeader.obj \
|
||||
$O\ChmIn.obj \
|
||||
|
||||
COMMON_OBJS = \
|
||||
$O\Alloc.obj \
|
||||
$O\IntToString.obj \
|
||||
$O\NewHandler.obj \
|
||||
$O\String.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\UTFConvert.obj \
|
||||
$O\Vector.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
$O\PropVariant.obj \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\InBuffer.obj \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
|
||||
COMPRESS_LZX_OBJS = \
|
||||
$O\LzxDecoder.obj \
|
||||
$O\Lzx86Converter.obj \
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
$(CHM_OBJS) \
|
||||
$(COMMON_OBJS) \
|
||||
$(WIN_OBJS) \
|
||||
$(7ZIP_COMMON_OBJS) \
|
||||
$(AR_COMMON_OBJS) \
|
||||
$(COMPRESS_LZX_OBJS) \
|
||||
$O\LZOutWindow.obj \
|
||||
$O\CopyCoder.obj \
|
||||
$O\resource.res
|
||||
|
||||
!include "../../../Build.mak"
|
||||
|
||||
$(CHM_OBJS): $(*B).cpp
|
||||
$(COMPL)
|
||||
$(COMMON_OBJS): ../../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(WIN_OBJS): ../../../Windows/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(AR_COMMON_OBJS): ../Common/$(*B).cpp
|
||||
$(COMPL)
|
||||
$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp
|
||||
$(COMPL_O2)
|
||||
$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp
|
||||
$(COMPL)
|
||||
$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
|
||||
$(COMPL)
|
||||
|
||||
3
7zip/Archive/Chm/resource.rc
Executable file
3
7zip/Archive/Chm/resource.rc
Executable file
@@ -0,0 +1,3 @@
|
||||
#include "../../MyVersionInfo.rc"
|
||||
|
||||
MY_VERSION_INFO_DLL("Chm Plugin", "chm")
|
||||
@@ -18,13 +18,3 @@ STDMETHODIMP CDummyOutStream::Write(const void *data,
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDummyOutStream::WritePart(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if(m_Stream)
|
||||
return m_Stream->WritePart(data, size, processedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialOutStream> m_Stream;
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "FilterCoder.h"
|
||||
#include "../../../Common/Alloc.h"
|
||||
#include "../../../Common/Defs.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
static const int kBufferSize = 1 << 17;
|
||||
|
||||
@@ -27,7 +28,7 @@ HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 siz
|
||||
size = (UInt32)remSize;
|
||||
}
|
||||
UInt32 processedSize = 0;
|
||||
RINOK(outStream->Write(_buffer, size, &processedSize));
|
||||
RINOK(WriteStream(outStream, _buffer, size, &processedSize));
|
||||
if (size != processedSize)
|
||||
return E_FAIL;
|
||||
_nowPos64 += processedSize;
|
||||
@@ -47,8 +48,10 @@ STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
|
||||
while(NeedMore())
|
||||
{
|
||||
UInt32 processedSize;
|
||||
UInt32 size = kBufferSize - bufferPos;
|
||||
RINOK(inStream->Read(_buffer + bufferPos, size, &processedSize));
|
||||
|
||||
// Change it: It can be optimized using ReadPart
|
||||
RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
|
||||
|
||||
UInt32 endPos = bufferPos + processedSize;
|
||||
|
||||
bufferPos = Filter->Filter(_buffer, endPos);
|
||||
@@ -131,11 +134,6 @@ STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processe
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::Flush()
|
||||
{
|
||||
if (_bufferPos != 0)
|
||||
@@ -149,7 +147,7 @@ STDMETHODIMP CFilterCoder::Flush()
|
||||
return E_FAIL;
|
||||
}
|
||||
UInt32 processedSize;
|
||||
RINOK(_outStream->Write(_buffer, _bufferPos, &processedSize));
|
||||
RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
|
||||
if (_bufferPos != processedSize)
|
||||
return E_FAIL;
|
||||
_bufferPos = 0;
|
||||
@@ -189,7 +187,7 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
data = (void *)((Byte *)data + sizeTemp);
|
||||
size -= sizeTemp;
|
||||
processedSizeTotal += sizeTemp;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
|
||||
@@ -198,7 +196,8 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_convertedPosBegin = _convertedPosEnd = 0;
|
||||
UInt32 processedSizeTemp;
|
||||
UInt32 size0 = kBufferSize - _bufferPos;
|
||||
RINOK(_inStream->Read(_buffer + _bufferPos, size0, &processedSizeTemp));
|
||||
// Optimize it:
|
||||
RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
|
||||
_bufferPos = _bufferPos + processedSizeTemp;
|
||||
_convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
|
||||
if (_convertedPosEnd == 0)
|
||||
@@ -217,11 +216,6 @@ STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CFilterCoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
// #endif // _ST_MODE
|
||||
|
||||
#ifndef _NO_CRYPTO
|
||||
|
||||
@@ -94,11 +94,9 @@ public:
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize); \
|
||||
STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
|
||||
STDMETHOD(ReleaseOutStream)();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Flush)();
|
||||
// #endif
|
||||
|
||||
|
||||
@@ -16,18 +16,6 @@ STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSequentialInStreamWithCRC::ReadPart(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Read(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
@@ -40,18 +28,6 @@ STDMETHODIMP CInStreamWithCRC::Read(void *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::ReadPart(void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result = _stream->ReadPart(data, size, &realProcessedSize);
|
||||
_size += realProcessedSize;
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset,
|
||||
UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,6 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _stream;
|
||||
UInt64 _size;
|
||||
@@ -40,7 +39,6 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
private:
|
||||
CMyComPtr<IInStream> _stream;
|
||||
|
||||
@@ -28,17 +28,11 @@ STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
_pos += realProcessed;
|
||||
_seekPos += realProcessed;
|
||||
RINOK(result);
|
||||
if (realProcessed == 0)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Read(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
|
||||
UInt64 *newPosition)
|
||||
{
|
||||
@@ -113,7 +107,6 @@ public:
|
||||
|
||||
HRESULT Flush();
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
};
|
||||
|
||||
HRESULT COutVolumeStream::Flush()
|
||||
@@ -179,17 +172,12 @@ STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *proce
|
||||
_streamIndex++;
|
||||
_offsetPos = 0;
|
||||
}
|
||||
if (realProcessed != curSize)
|
||||
if (realProcessed != curSize && realProcessed == 0)
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
return Write(data, size, processedSize);
|
||||
}
|
||||
|
||||
STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
|
||||
{
|
||||
if(seekOrigin >= 3)
|
||||
|
||||
@@ -36,7 +36,6 @@ public:
|
||||
MY_UNKNOWN_IMP1(IInStream)
|
||||
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
|
||||
@@ -70,7 +69,6 @@ public:
|
||||
MY_UNKNOWN_IMP1(IOutStream)
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
|
||||
};
|
||||
*/
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result;
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
@@ -21,21 +21,3 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::WritePart(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
result = S_OK;
|
||||
}
|
||||
else
|
||||
result = _stream->WritePart(data, size, &realProcessedSize);
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CCRC _crc;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
|
||||
@@ -14,6 +14,7 @@ COMMON_OBJS = \
|
||||
$O\NewHandler.obj \
|
||||
$O\String.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\Vector.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
@@ -22,6 +23,7 @@ WIN_OBJS = \
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
|
||||
@@ -154,6 +154,14 @@ SOURCE=..\..\..\Common\StringConvert.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringToInt.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\StringToInt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\Common\Vector.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
@@ -248,6 +256,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
#include "DebIn.h"
|
||||
#include "DebHeader.h"
|
||||
|
||||
#include "Common/StringToInt.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NDeb {
|
||||
|
||||
@@ -14,7 +17,7 @@ using namespace NHeader;
|
||||
|
||||
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
|
||||
{
|
||||
RINOK(m_Stream->Read(data, size, &processedSize));
|
||||
RINOK(ReadStream(m_Stream, data, size, &processedSize));
|
||||
m_Position += processedSize;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -24,7 +27,7 @@ HRESULT CInArchive::Open(IInStream *inStream)
|
||||
RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
|
||||
char signature[kSignatureLen];
|
||||
UInt32 processedSize;
|
||||
RINOK(inStream->Read(signature, kSignatureLen, &processedSize));
|
||||
RINOK(ReadStream(inStream, signature, kSignatureLen, &processedSize));
|
||||
m_Position += processedSize;
|
||||
if (processedSize != kSignatureLen)
|
||||
return S_FALSE;
|
||||
@@ -34,40 +37,50 @@ HRESULT CInArchive::Open(IInStream *inStream)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static bool CheckString(const char *srcString, int numChars, int radix)
|
||||
static bool OctalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
for(int i = 0; i < numChars; i++)
|
||||
{
|
||||
char c = srcString[i];
|
||||
if (c == 0)
|
||||
return true;
|
||||
if (c >= '0' && c <= '0' + radix - 1)
|
||||
continue;
|
||||
if (c != ' ')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
char sz[32];
|
||||
strncpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
for (i = 0; sz[i] == ' '; i++);
|
||||
res = ConvertOctStringToUInt64(sz + i, &end);
|
||||
return (*end == ' ' || *end == 0);
|
||||
}
|
||||
static bool CheckOctalString(const char *srcString, int numChars)
|
||||
{ return CheckString(srcString, numChars, 8); }
|
||||
static bool CheckDecimalString(const char *srcString, int numChars)
|
||||
{ return CheckString(srcString, numChars, 10); }
|
||||
|
||||
#define ReturnIfBadOctal(x, y) { if (!CheckOctalString((x), (y))) return S_FALSE; }
|
||||
#define ReturnIfBadDecimal(x, y) { if (!CheckDecimalString((x), (y))) return S_FALSE; }
|
||||
|
||||
static UInt32 StringToNumber(const char *srcString, int numChars, int radix)
|
||||
static bool OctalToNumber32(const char *s, int size, UInt32 &res)
|
||||
{
|
||||
AString modString;
|
||||
for (int i = 0; i < numChars; i++)
|
||||
modString += srcString[i];
|
||||
char *endPtr;
|
||||
return strtoul(modString, &endPtr, radix);
|
||||
UInt64 res64;
|
||||
if (!OctalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
static UInt32 OctalToNumber(const char *srcString, int numChars)
|
||||
{ return StringToNumber(srcString, numChars, 8); }
|
||||
static UInt32 DecimalToNumber(const char *srcString, int numChars)
|
||||
{ return StringToNumber(srcString, numChars, 10); }
|
||||
|
||||
static bool DecimalToNumber(const char *s, int size, UInt64 &res)
|
||||
{
|
||||
char sz[32];
|
||||
strncpy(sz, s, size);
|
||||
sz[size] = 0;
|
||||
const char *end;
|
||||
int i;
|
||||
for (i = 0; sz[i] == ' '; i++);
|
||||
res = ConvertStringToUInt64(sz + i, &end);
|
||||
return (*end == ' ' || *end == 0);
|
||||
}
|
||||
|
||||
static bool DecimalToNumber32(const char *s, int size, UInt32 &res)
|
||||
{
|
||||
UInt64 res64;
|
||||
if (!DecimalToNumber(s, size, res64))
|
||||
return false;
|
||||
res = (UInt32)res64;
|
||||
return (res64 <= 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#define RIF(x) { if (!(x)) return S_FALSE; }
|
||||
|
||||
|
||||
HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
{
|
||||
@@ -93,18 +106,15 @@ HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
|
||||
if (((Byte)item.Name[i]) < 0x20)
|
||||
return S_FALSE;
|
||||
|
||||
ReturnIfBadDecimal(cur, kTimeSize);
|
||||
item.ModificationTime = DecimalToNumber(cur, kTimeSize);
|
||||
RIF(DecimalToNumber32(cur, kTimeSize, item.ModificationTime));
|
||||
cur += kTimeSize;
|
||||
|
||||
cur += 6 + 6;
|
||||
|
||||
ReturnIfBadOctal(cur, kModeSize);
|
||||
item.Mode = OctalToNumber(cur, kModeSize);
|
||||
RIF(OctalToNumber32(cur, kModeSize, item.Mode));
|
||||
cur += kModeSize;
|
||||
|
||||
ReturnIfBadDecimal(cur, kSizeSize);
|
||||
item.Size = DecimalToNumber(cur, kSizeSize);
|
||||
RIF(DecimalToNumber(cur, kSizeSize, item.Size));
|
||||
cur += kSizeSize;
|
||||
|
||||
filled = true;
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "DebHandler.h"
|
||||
#include "../../ICoder.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-0001100C0000}
|
||||
// {23170F69-40C1-278A-1000-000110EC0000}
|
||||
DEFINE_GUID(CLSID_CDebHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0C, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEC, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
|
||||
@@ -14,6 +14,7 @@ COMMON_OBJS = \
|
||||
$O\NewHandler.obj \
|
||||
$O\String.obj \
|
||||
$O\StringConvert.obj \
|
||||
$O\StringToInt.obj \
|
||||
$O\Vector.obj \
|
||||
|
||||
WIN_OBJS = \
|
||||
@@ -22,6 +23,7 @@ WIN_OBJS = \
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "../../ICoder.h"
|
||||
#include "GZipHandler.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110030000}
|
||||
// {23170F69-40C1-278A-1000-000110EF0000}
|
||||
DEFINE_GUID(CLSID_CGZipHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEF, 0x00, 0x00);
|
||||
|
||||
// {23170F69-40C1-278B-0401-080000000100}
|
||||
DEFINE_GUID(CLSID_CCompressDeflateEncoder,
|
||||
|
||||
@@ -264,6 +264,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
|
||||
@@ -58,12 +58,14 @@ static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
|
||||
|
||||
static const wchar_t *kUnknownOS = L"Unknown";
|
||||
|
||||
/*
|
||||
enum // PropID
|
||||
{
|
||||
// kpidExtraIsPresent = kpidUserDefined,
|
||||
// kpidExtraFlags,
|
||||
// kpidIsText
|
||||
kpidExtraIsPresent = kpidUserDefined,
|
||||
kpidExtraFlags,
|
||||
kpidIsText
|
||||
};
|
||||
*/
|
||||
|
||||
STATPROPSTG kProperties[] =
|
||||
{
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
#include "Common/MyCom.h"
|
||||
#include "Windows/Defs.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NGZip {
|
||||
|
||||
HRESULT CInArchive::ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
RINOK(inStream->Read(data, size, &realProcessedSize));
|
||||
RINOK(ReadStream(inStream, data, size, &realProcessedSize));
|
||||
m_Position += realProcessedSize;
|
||||
if(realProcessedSize != size)
|
||||
return S_FALSE;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "GZipOut.h"
|
||||
#include "Common/CRC.h"
|
||||
#include "Windows/Defs.h"
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NGZip {
|
||||
@@ -12,7 +13,7 @@ namespace NGZip {
|
||||
HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
|
||||
{
|
||||
UInt32 processedSize;
|
||||
RINOK(m_Stream->Write(buffer, size, &processedSize));
|
||||
RINOK(WriteStream(m_Stream, buffer, size, &processedSize));
|
||||
if(processedSize != size)
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
|
||||
@@ -26,6 +26,7 @@ WIN_OBJS = \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\CodecsPath.obj \
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
#include "../IProgress.h"
|
||||
#include "../PropID.h"
|
||||
|
||||
// MIDL_INTERFACE("23170F69-40C1-278A-0000-000600xx0000")
|
||||
#define ARCHIVE_INTERFACE_SUB(i, base, x) \
|
||||
DEFINE_GUID(IID_ ## i, \
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x06, 0x00, x, 0x00, 0x00); \
|
||||
struct i: public base
|
||||
|
||||
#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
|
||||
|
||||
namespace NFileTimeType
|
||||
{
|
||||
enum EEnum
|
||||
@@ -29,6 +37,7 @@ namespace NArchive
|
||||
kKeepName,
|
||||
kStartSignature,
|
||||
kFinishSignature,
|
||||
kAssociate
|
||||
};
|
||||
|
||||
namespace NExtract
|
||||
@@ -66,24 +75,15 @@ namespace NArchive
|
||||
}
|
||||
}
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100010000}
|
||||
DEFINE_GUID(IID_IArchiveOpenCallback,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100010000")
|
||||
IArchiveOpenCallback: public IUnknown
|
||||
ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE;
|
||||
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE;
|
||||
};
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100090000}
|
||||
DEFINE_GUID(IID_IArchiveExtractCallback,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100090000")
|
||||
IArchiveExtractCallback: public IProgress
|
||||
|
||||
ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,
|
||||
Int32 askExtractMode) PURE;
|
||||
// GetStream OUT: S_OK - OK, S_FALSE - skeep this file
|
||||
@@ -92,36 +92,27 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// {23170F69-40C1-278A-0000-0001000D0000}
|
||||
DEFINE_GUID(IID_IArchiveOpenVolumeCallback,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000D0000")
|
||||
IArchiveOpenVolumeCallback: public IUnknown
|
||||
ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE;
|
||||
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE;
|
||||
};
|
||||
|
||||
|
||||
// {23170F69-40C1-278A-0000-0001000D0100}
|
||||
DEFINE_GUID(IID_IArchiveOpenSetSubArchiveName,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x01, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000D0100")
|
||||
IArchiveOpenSetSubArchiveName: public IUnknown
|
||||
ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
|
||||
{
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
|
||||
};
|
||||
|
||||
|
||||
ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
|
||||
};
|
||||
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100080000}
|
||||
DEFINE_GUID(IID_IInArchive,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100080000")
|
||||
IInArchive: public IUnknown
|
||||
ARCHIVE_INTERFACE(IInArchive, 0x60)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition,
|
||||
IArchiveOpenCallback *openArchiveCallback) PURE;
|
||||
STDMETHOD(Close)() PURE;
|
||||
@@ -129,6 +120,9 @@ public:
|
||||
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
|
||||
STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
|
||||
Int32 testMode, IArchiveExtractCallback *extractCallback) PURE;
|
||||
// indices must be sorted
|
||||
// numItems = 0xFFFFFFFF means all files
|
||||
// testMode != 0 means "test files operation"
|
||||
|
||||
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE;
|
||||
|
||||
@@ -141,25 +135,9 @@ public:
|
||||
BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
|
||||
};
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100080100}
|
||||
DEFINE_GUID(IID_IInArchiveGetStream,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x01, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100080100")
|
||||
IInArchiveGetStream: public IUnknown
|
||||
{
|
||||
public:
|
||||
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
|
||||
};
|
||||
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100040000}
|
||||
DEFINE_GUID(IID_IArchiveUpdateCallback,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100040000")
|
||||
IArchiveUpdateCallback: public IProgress
|
||||
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
|
||||
{
|
||||
public:
|
||||
// STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator) PURE;
|
||||
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
|
||||
Int32 *newData, // 1 - new data, 0 - old data
|
||||
Int32 *newProperties, // 1 - new properties, 0 - old properties
|
||||
@@ -170,33 +148,23 @@ public:
|
||||
STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
|
||||
};
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100040002}
|
||||
DEFINE_GUID(IID_IArchiveUpdateCallback2,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100040002")
|
||||
IArchiveUpdateCallback2: public IArchiveUpdateCallback
|
||||
|
||||
ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
|
||||
{
|
||||
public:
|
||||
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE;
|
||||
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE;
|
||||
};
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100020000}
|
||||
DEFINE_GUID(IID_IOutArchive,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100020000")
|
||||
IOutArchive: public IUnknown
|
||||
|
||||
ARCHIVE_INTERFACE(IOutArchive, 0xA0)
|
||||
{
|
||||
STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems,
|
||||
IArchiveUpdateCallback *updateCallback) PURE;
|
||||
STDMETHOD(GetFileTimeType)(UInt32 *type) PURE;
|
||||
};
|
||||
|
||||
// {23170F69-40C1-278A-0000-000100030000}
|
||||
DEFINE_GUID(IID_ISetProperties,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
|
||||
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100030000")
|
||||
ISetProperties: public IUnknown
|
||||
|
||||
ARCHIVE_INTERFACE(ISetProperties, 0x03)
|
||||
{
|
||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
|
||||
};
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "../../ICoder.h"
|
||||
#include "LzhHandler.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-0001100E0000}
|
||||
// {23170F69-40C1-278A-1000-000110060000}
|
||||
DEFINE_GUID(CLSID_CLzhHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x0E, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
|
||||
@@ -290,12 +290,28 @@ SOURCE=..\..\Common\MSBFDecoder.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
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Archive Common"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/ Archive/arj/InEngine.cpp
|
||||
// Archive/arj/InEngine.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Common/Buffer.h"
|
||||
#include "Common/CRC.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
#include "LzhIn.h"
|
||||
|
||||
namespace NArchive {
|
||||
@@ -13,7 +15,7 @@ namespace NLzh {
|
||||
|
||||
HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
|
||||
{
|
||||
RINOK(m_Stream->Read(data, size, &processedSize));
|
||||
RINOK(ReadStream(m_Stream, data, size, &processedSize));
|
||||
m_Position += processedSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,14 @@ public:
|
||||
{
|
||||
int index = FindExt(kExtIdUnixTime);
|
||||
if (index < 0)
|
||||
{
|
||||
if (Level == 2)
|
||||
{
|
||||
value = ModifiedTime;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const Byte *data = (const Byte *)(Extensions[index].Data);
|
||||
value = data[0] |
|
||||
((UInt32)data[1] << 8) |
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
namespace NArchive {
|
||||
namespace NLzh {
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT result;
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
@@ -25,22 +24,4 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data,
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP COutStreamWithCRC::WritePart(const void *data,
|
||||
UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 realProcessedSize;
|
||||
HRESULT result;
|
||||
if(!_stream)
|
||||
{
|
||||
realProcessedSize = size;
|
||||
result = S_OK;
|
||||
}
|
||||
else
|
||||
result = _stream->WritePart(data, size, &realProcessedSize);
|
||||
_crc.Update(data, realProcessedSize);
|
||||
if(processedSize != NULL)
|
||||
*processedSize = realProcessedSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||
private:
|
||||
CCRC _crc;
|
||||
CMyComPtr<ISequentialOutStream> _stream;
|
||||
|
||||
@@ -23,7 +23,9 @@ WIN_OBJS = \
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\InBuffer.obj \
|
||||
$O\LimitedStreams.obj \
|
||||
$O\OutBuffer.obj \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
AR_COMMON_OBJS = \
|
||||
$O\ItemNameUtils.obj \
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include "../../ICoder.h"
|
||||
#include "RpmHandler.h"
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110090000}
|
||||
// {23170F69-40C1-278A-1000-000110EB0000}
|
||||
DEFINE_GUID(CLSID_CRpmHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEB, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
|
||||
@@ -140,6 +140,14 @@ SOURCE=..\..\Common\ProgressUtils.cpp
|
||||
|
||||
SOURCE=..\..\Common\ProgressUtils.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Compress"
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "Windows/Defs.h"
|
||||
#include "Common/MyCom.h"
|
||||
|
||||
#include "../../Common/StreamUtils.h"
|
||||
|
||||
namespace NArchive {
|
||||
namespace NRpm {
|
||||
|
||||
@@ -31,7 +33,7 @@ static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
|
||||
char dat[kCSigHeaderSigSize];
|
||||
char *cur = dat;
|
||||
UInt32 processedSize;
|
||||
RINOK(inStream->Read(dat, kCSigHeaderSigSize, &processedSize));
|
||||
RINOK(ReadStream(inStream, dat, kCSigHeaderSigSize, &processedSize));
|
||||
if (kCSigHeaderSigSize != processedSize)
|
||||
return S_FALSE;
|
||||
memmove(h.Magic, cur, 4);
|
||||
@@ -50,7 +52,7 @@ HRESULT OpenArchive(IInStream *inStream)
|
||||
char *cur = leadData;
|
||||
CLead lead;
|
||||
UInt32 processedSize;
|
||||
RINOK(inStream->Read(leadData, kLeadSize, &processedSize));
|
||||
RINOK(ReadStream(inStream, leadData, kLeadSize, &processedSize));
|
||||
if (kLeadSize != processedSize)
|
||||
return S_FALSE;
|
||||
memmove(lead.Magic, cur, 4);
|
||||
|
||||
@@ -17,6 +17,7 @@ WIN_OBJS = \
|
||||
|
||||
7ZIP_COMMON_OBJS = \
|
||||
$O\ProgressUtils.obj \
|
||||
$O\StreamUtils.obj \
|
||||
|
||||
OBJS = \
|
||||
$O\StdAfx.obj \
|
||||
|
||||
@@ -46,9 +46,9 @@ DEFINE_GUID(CLSID_CCryptoRar29Decoder,
|
||||
0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00);
|
||||
*/
|
||||
|
||||
// {23170F69-40C1-278A-1000-000110020000}
|
||||
// {23170F69-40C1-278A-1000-000110030000}
|
||||
DEFINE_GUID(CLSID_CRarHandler,
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 0x00, 0x00);
|
||||
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00);
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
|
||||
@@ -178,6 +178,14 @@ SOURCE=..\..\..\Common\Types.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
|
||||
@@ -400,6 +408,14 @@ SOURCE=..\..\Common\StreamObjects.cpp
|
||||
|
||||
SOURCE=..\..\Common\StreamObjects.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Common\StreamUtils.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "7z"
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||
switch(propID)
|
||||
{
|
||||
case kpidPath:
|
||||
if (item.HasUnicodeName())
|
||||
if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty())
|
||||
propVariant = item.UnicodeName;
|
||||
else
|
||||
propVariant = (const wchar_t *)MultiByteToUnicodeString(item.Name, CP_OEMCP);
|
||||
@@ -615,6 +615,7 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
|
||||
NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec;
|
||||
CMyComPtr<ICompressFilter> rar20CryptoDecoder;
|
||||
NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec;
|
||||
CMyComPtr<ICompressFilter> rar29CryptoDecoder;
|
||||
|
||||
CFolderInStream *folderInStreamSpec = NULL;
|
||||
@@ -727,9 +728,11 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||
{
|
||||
if (!rar29CryptoDecoder)
|
||||
{
|
||||
rar29CryptoDecoder = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
|
||||
rar29CryptoDecoder = rar29CryptoDecoderSpec;
|
||||
// RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
|
||||
}
|
||||
rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
|
||||
CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
|
||||
RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
|
||||
&cryptoProperties));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user