// Archive/WimIn.h #ifndef __ARCHIVE_WIM_IN_H #define __ARCHIVE_WIM_IN_H #include "Common/MyString.h" #include "Common/Buffer.h" #include "../../Compress/Lzx/LzxDecoder.h" #include "../../Compress/Copy/CopyCoder.h" namespace NArchive { namespace NWim { namespace NResourceFlags { const Byte Compressed = 4; const Byte kMetadata = 2; } struct CResource { UInt64 PackSize; UInt64 Offset; UInt64 UnpackSize; Byte Flags; bool IsCompressed() const { return (Flags & NResourceFlags::Compressed) != 0; } bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 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; } struct CHeader { UInt32 Flags; UInt32 Version; // UInt32 ChunkSize; UInt16 PartNumber; UInt16 NumParts; UInt32 NumImages; Byte Guid[16]; CResource OffsetResource; CResource XmlResource; CResource MetadataResource; /* CResource IntegrityResource; UInt32 BootIndex; */ bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; } bool IsSupported() const { return (!IsCompressed() || (Flags & NHeaderFlags::kLZX) != 0); } bool IsSpanned() const { return (!IsCompressed() || (Flags & NHeaderFlags::kSpanned) != 0); } 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; BYTE Hash[kHashSize]; }; struct CItem { UString Name; UInt32 Attributes; // UInt32 SecurityId; BYTE Hash[kHashSize]; FILETIME CreationTime; FILETIME LastAccessTime; FILETIME LastWriteTime; // UInt32 ReparseTag; // UInt64 HardLink; // UInt16 NumStreams; // UInt16 ShortNameLen; int StreamIndex; bool HasMetadata; CItem(): HasMetadata(true), StreamIndex(-1) {} bool IsDirectory() const { return HasMetadata && ((Attributes & 0x10) != 0); } bool HasStream() const { for (int i = 0; i < kHashSize; i++) if (Hash[i] != 0) return true; return false; } }; struct CDatabase { CRecordVector Streams; CObjectVector Items; 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(); } }; HRESULT ReadHeader(IInStream *inStream, CHeader &header); HRESULT OpenArchive(IInStream *inStream, const CHeader &header, CByteBuffer &xml, CDatabase &database); HRESULT SortDatabase(CDatabase &database); class CUnpacker { NCompress::CCopyCoder *copyCoderSpec; CMyComPtr copyCoder; NCompress::NLzx::CDecoder *lzxDecoderSpec; CMyComPtr lzxDecoder; CByteBuffer sizesBuf; HRESULT Unpack(IInStream *inStream, const CResource &res, ISequentialOutStream *outStream, ICompressProgressInfo *progress); public: HRESULT Unpack(IInStream *inStream, const CResource &res, ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest); }; }} #endif