diff options
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Wim/WimIn.h')
-rw-r--r-- | src/libs/7zip/win/CPP/7zip/Archive/Wim/WimIn.h | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Wim/WimIn.h b/src/libs/7zip/win/CPP/7zip/Archive/Wim/WimIn.h new file mode 100644 index 000000000..da3e28a56 --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/Archive/Wim/WimIn.h @@ -0,0 +1,297 @@ +// Archive/WimIn.h + +#ifndef __ARCHIVE_WIM_IN_H +#define __ARCHIVE_WIM_IN_H + +#include "Common/Buffer.h" +#include "Common/MyString.h" + +#include "../../Compress/CopyCoder.h" +#include "../../Compress/LzxDecoder.h" + +#include "../IArchive.h" + +namespace NArchive { +namespace NWim { + +namespace NXpress { + +class CBitStream +{ + CInBuffer m_Stream; + UInt32 m_Value; + unsigned m_BitPos; +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() { m_Stream.Init(); m_BitPos = 0; } + // UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize() - m_BitPos / 8; } + Byte DirectReadByte() { return m_Stream.ReadByte(); } + + void Normalize() + { + if (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; + m_BitPos += 16; + } + } + + UInt32 GetValue(unsigned numBits) + { + Normalize(); + return (m_Value >> (m_BitPos - numBits)) & ((1 << numBits) - 1); + } + + void MovePos(unsigned numBits) { m_BitPos -= numBits; } + + UInt32 ReadBits(unsigned numBits) + { + UInt32 res = GetValue(numBits); + m_BitPos -= numBits; + return res; + } +}; + +const unsigned kNumHuffmanBits = 16; +const UInt32 kMatchMinLen = 3; +const UInt32 kNumLenSlots = 16; +const UInt32 kNumPosSlots = 16; +const UInt32 kNumPosLenSlots = kNumPosSlots * kNumLenSlots; +const UInt32 kMainTableSize = 256 + kNumPosLenSlots; + +class CDecoder +{ + CBitStream m_InBitStream; + CLzOutWindow m_OutWindowStream; + NCompress::NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder; + + HRESULT CodeSpec(UInt32 size); + HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize); +public: + void ReleaseStreams() + { + m_OutWindowStream.ReleaseStream(); + m_InBitStream.ReleaseStream(); + } + HRESULT Flush() { return m_OutWindowStream.Flush(); } + HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize); +}; + +} + +namespace NResourceFlags +{ + const Byte kFree = 1; + const Byte kMetadata = 2; + const Byte Compressed = 4; + const Byte Spanned = 4; +} + +struct CResource +{ + UInt64 PackSize; + UInt64 Offset; + UInt64 UnpackSize; + Byte Flags; + + void Clear() + { + PackSize = 0; + Offset = 0; + UnpackSize = 0; + Flags = 0; + } + void Parse(const Byte *p); + void WriteTo(Byte *p) const; + bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; } + bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; } + bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; } + bool IsEmpty() const { return (UnpackSize == 0); } +}; + +namespace NHeaderFlags +{ + const UInt32 kCompression = 2; + const UInt32 kSpanned = 8; + const UInt32 kRpFix = 0x80; + const UInt32 kXPRESS = 0x20000; + const UInt32 kLZX = 0x40000; +} + +const UInt32 kWimVersion = 0x010D00; +const UInt32 kHeaderSizeMax = 0xD0; +const UInt32 kSignatureSize = 8; +extern const Byte kSignature[kSignatureSize]; +const unsigned kChunkSizeBits = 15; +const UInt32 kChunkSize = (1 << kChunkSizeBits); + +struct CHeader +{ + UInt32 Version; + UInt32 Flags; + UInt32 ChunkSize; + Byte Guid[16]; + UInt16 PartNumber; + UInt16 NumParts; + UInt32 NumImages; + + CResource OffsetResource; + CResource XmlResource; + CResource MetadataResource; + CResource IntegrityResource; + UInt32 BootIndex; + + void SetDefaultFields(bool useLZX); + + void WriteTo(Byte *p) const; + HRESULT Parse(const Byte *p); + bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; } + bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0 || (Flags & NHeaderFlags::kXPRESS) != 0 ) ; } + bool IsLzxMode() const { return (Flags & NHeaderFlags::kLZX) != 0; } + bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); } + bool IsOldVersion() const { return (Version <= 0x010A00); } + bool IsNewVersion() const { return (Version > 0x010C00); } + + bool AreFromOnArchive(const CHeader &h) + { + return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts); + } +}; + +const UInt32 kHashSize = 20; +const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize; + +struct CStreamInfo +{ + CResource Resource; + UInt16 PartNumber; + UInt32 RefCount; + UInt32 Id; + BYTE Hash[kHashSize]; + + void WriteTo(Byte *p) const; +}; + +const UInt32 kDirRecordSizeOld = 62; +const UInt32 kDirRecordSize = 102; + +struct CItem +{ + UString Name; + UString ShortName; + UInt32 Attrib; + // UInt32 SecurityId; + BYTE Hash[kHashSize]; + UInt32 Id; + FILETIME CTime; + FILETIME ATime; + FILETIME MTime; + // UInt32 ReparseTag; + // UInt64 HardLink; + // UInt16 NumStreams; + int StreamIndex; + int Parent; + unsigned Order; + bool HasMetadata; + CItem(): HasMetadata(true), StreamIndex(-1), Id(0) {} + bool IsDir() const { return HasMetadata && ((Attrib & 0x10) != 0); } + bool HasStream() const + { + for (unsigned i = 0; i < kHashSize; i++) + if (Hash[i] != 0) + return true; + return Id != 0; + } +}; + +class CDatabase +{ + const Byte *DirData; + size_t DirSize; + size_t DirProcessed; + size_t DirStartOffset; + int Order; + IArchiveOpenCallback *OpenCallback; + + HRESULT ParseDirItem(size_t pos, int parent); + HRESULT ParseImageDirs(const CByteBuffer &buf, int parent); + +public: + CRecordVector<CStreamInfo> Streams; + CObjectVector<CItem> Items; + CIntVector SortedItems; + int NumImages; + bool SkipRoot; + bool ShowImageNumber; + + bool IsOldVersion; + + UInt64 GetUnpackSize() const + { + UInt64 res = 0; + for (int i = 0; i < Streams.Size(); i++) + res += Streams[i].Resource.UnpackSize; + return res; + } + + UInt64 GetPackSize() const + { + UInt64 res = 0; + for (int i = 0; i < Streams.Size(); i++) + res += Streams[i].Resource.PackSize; + return res; + } + + void Clear() + { + Streams.Clear(); + Items.Clear(); + SortedItems.Clear(); + NumImages = 0; + + SkipRoot = true; + ShowImageNumber = true; + IsOldVersion = false; + } + + UString GetItemPath(int index) const; + + HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback); + + void DetectPathMode() + { + ShowImageNumber = (NumImages != 1); + } + + HRESULT Sort(bool skipRootDir); +}; + +HRESULT ReadHeader(IInStream *inStream, CHeader &header); + +class CUnpacker +{ + NCompress::CCopyCoder *copyCoderSpec; + CMyComPtr<ICompressCoder> copyCoder; + + NCompress::NLzx::CDecoder *lzxDecoderSpec; + CMyComPtr<ICompressCoder> lzxDecoder; + + NXpress::CDecoder xpressDecoder; + + CByteBuffer sizesBuf; + HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress); +public: + HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode, + ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest); +}; + +}} + +#endif |