Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Archive/Wim/WimIn.h')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Wim/WimIn.h355
1 files changed, 283 insertions, 72 deletions
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index da3e28a5..4b7c6d95 100755..100644
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -3,8 +3,10 @@
#ifndef __ARCHIVE_WIM_IN_H
#define __ARCHIVE_WIM_IN_H
-#include "Common/Buffer.h"
-#include "Common/MyString.h"
+#include "../../../Common/MyBuffer.h"
+#include "../../../Common/MyXml.h"
+
+#include "../../../Windows/PropVariant.h"
#include "../../Compress/CopyCoder.h"
#include "../../Compress/LzxDecoder.h"
@@ -14,6 +16,104 @@
namespace NArchive {
namespace NWim {
+const UInt32 kDirRecordSizeOld = 62;
+const UInt32 kDirRecordSize = 102;
+
+/*
+ There is error in WIM specification about dwReparseTag, dwReparseReserved and liHardLink fields.
+
+ Correct DIRENTRY structure:
+ {
+ hex offset
+ 0 UInt64 Len;
+ 8 UInt32 Attrib;
+ C UInt32 SecurityId;
+
+ 10 UInt64 SubdirOffset; // = 0 for files
+
+ 18 UInt64 unused1; // = 0?
+ 20 UInt64 unused2; // = 0?
+
+ 28 UInt64 CTime;
+ 30 UInt64 ATime;
+ 38 UInt64 MTime;
+
+ 40 Byte Sha1[20];
+
+ 54 UInt32 Unknown1; // is it 0 always?
+
+
+ union
+ {
+ 58 UInt64 NtNodeId;
+ {
+ 58 UInt32 ReparseTag;
+ 5C UInt32 ReparseFlags; // is it 0 always? Check with new imagex.
+ }
+ }
+
+ 60 UInt16 Streams;
+
+ 62 UInt16 ShortNameLen;
+ 64 UInt16 FileNameLen;
+
+ 66 UInt16 Name[];
+ UInt16 ShortName[];
+ }
+
+ // DIRENTRY for WIM_VERSION <= 1.10
+ DIRENTRY_OLD structure:
+ {
+ hex offset
+ 0 UInt64 Len;
+ 8 UInt32 Attrib;
+ C UInt32 SecurityId;
+
+ union
+ {
+ 10 UInt64 SubdirOffset; //
+
+ 10 UInt32 OldWimFileId; // used for files in old WIMs
+ 14 UInt32 OldWimFileId_Reserved; // = 0
+ }
+
+ 18 UInt64 CTime;
+ 20 UInt64 ATime;
+ 28 UInt64 MTime;
+
+ 30 UInt64 Unknown; // NtNodeId ?
+
+ 38 UInt16 Streams;
+ 3A UInt16 ShortNameLen;
+ 3C UInt16 FileNameLen;
+ 3E UInt16 FileName[];
+ UInt16 ShortName[];
+ }
+
+ ALT_STREAM structure:
+ {
+ hex offset
+ 0 UInt64 Len;
+ 8 UInt64 Unused;
+ 10 Byte Sha1[20];
+ 24 UInt16 FileNameLen;
+ 26 UInt16 FileName[];
+ }
+
+ ALT_STREAM_OLD structure:
+ {
+ hex offset
+ 0 UInt64 Len;
+ 8 UInt64 StreamId; // 32-bit value
+ 10 UInt16 FileNameLen;
+ 12 UInt16 FileName[];
+ }
+
+ If item is file (not Directory) and there are alternative streams,
+ there is additional ALT_STREAM item of main "unnamed" stream in Streams array.
+
+*/
+
namespace NXpress {
class CBitStream
@@ -24,7 +124,6 @@ class CBitStream
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; }
@@ -74,11 +173,6 @@ class CDecoder
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);
};
@@ -90,7 +184,7 @@ namespace NResourceFlags
const Byte kFree = 1;
const Byte kMetadata = 2;
const Byte Compressed = 4;
- const Byte Spanned = 4;
+ // const Byte Spanned = 4;
}
struct CResource
@@ -107,7 +201,16 @@ struct CResource
UnpackSize = 0;
Flags = 0;
}
+ UInt64 GetEndLimit() const { return Offset + PackSize; }
void Parse(const Byte *p);
+ void ParseAndUpdatePhySize(const Byte *p, UInt64 &phySize)
+ {
+ Parse(p);
+ UInt64 v = GetEndLimit();
+ if (phySize < v)
+ phySize = v;
+ }
+
void WriteTo(Byte *p) const;
bool IsFree() const { return (Flags & NResourceFlags::kFree) != 0; }
bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }
@@ -117,16 +220,21 @@ struct CResource
namespace NHeaderFlags
{
- const UInt32 kCompression = 2;
- const UInt32 kSpanned = 8;
- const UInt32 kRpFix = 0x80;
- const UInt32 kXPRESS = 0x20000;
- const UInt32 kLZX = 0x40000;
+ const UInt32 kCompression = 2;
+ const UInt32 kReadOnly = 4;
+ const UInt32 kSpanned = 8;
+ const UInt32 kResourceOnly = 0x10;
+ const UInt32 kMetadataOnly = 0x20;
+ const UInt32 kWriteInProgress = 0x40;
+ const UInt32 kReparsePointFixup = 0x80;
+ const UInt32 kXPRESS = 0x20000;
+ const UInt32 kLZX = 0x40000;
}
const UInt32 kWimVersion = 0x010D00;
-const UInt32 kHeaderSizeMax = 0xD0;
-const UInt32 kSignatureSize = 8;
+
+const unsigned kHeaderSizeMax = 0xD0;
+const unsigned kSignatureSize = 8;
extern const Byte kSignature[kSignatureSize];
const unsigned kChunkSizeBits = 15;
const UInt32 kChunkSize = (1 << kChunkSizeBits);
@@ -150,7 +258,7 @@ struct CHeader
void SetDefaultFields(bool useLZX);
void WriteTo(Byte *p) const;
- HRESULT Parse(const Byte *p);
+ HRESULT Parse(const Byte *p, UInt64 &phySize);
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; }
@@ -164,115 +272,217 @@ struct CHeader
}
};
-const UInt32 kHashSize = 20;
-const UInt32 kStreamInfoSize = 24 + 2 + 4 + kHashSize;
+const unsigned kHashSize = 20;
+const unsigned kStreamInfoSize = 24 + 2 + 4 + kHashSize;
struct CStreamInfo
{
CResource Resource;
- UInt16 PartNumber;
+ UInt16 PartNumber; // for NEW WIM format, we set it to 1 for OLD WIM format
UInt32 RefCount;
- UInt32 Id;
- BYTE Hash[kHashSize];
+ UInt32 Id; // for OLD WIM format
+ 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;
+ size_t Offset;
+ int IndexInSorted;
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
+ int ImageIndex; // -1 means that file is unreferenced in Images (deleted item?)
+ bool IsDir;
+ bool IsAltStream;
+
+ bool HasMetadata() const { return ImageIndex >= 0; }
+
+ CItem():
+ IndexInSorted(-1),
+ StreamIndex(-1),
+ Parent(-1),
+ IsDir(false),
+ IsAltStream(false)
+ {}
+};
+
+struct CImage
+{
+ CByteBuffer Meta;
+ CRecordVector<UInt32> SecurOffsets;
+ unsigned StartItem;
+ unsigned NumItems;
+ unsigned NumEmptyRootItems;
+ int VirtualRootIndex; // index in CDatabase::VirtualRoots[]
+ UString RootName;
+ CByteBuffer RootNameBuf;
+
+ CImage(): VirtualRootIndex(-1) {}
+};
+
+struct CImageInfo
+{
+ bool CTimeDefined;
+ bool MTimeDefined;
+ bool NameDefined;
+ bool IndexDefined;
+
+ FILETIME CTime;
+ FILETIME MTime;
+ UString Name;
+
+ UInt64 DirCount;
+ UInt64 FileCount;
+ UInt32 Index;
+
+ int ItemIndexInXml;
+
+ UInt64 GetTotalFilesAndDirs() const { return DirCount + FileCount; }
+
+ CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false),
+ IndexDefined(false), ItemIndexInXml(-1) {}
+ void Parse(const CXmlItem &item);
+};
+
+struct CWimXml
+{
+ CByteBuffer Data;
+ CXml Xml;
+
+ UInt16 VolIndex;
+ CObjectVector<CImageInfo> Images;
+
+ UString FileName;
+
+ UInt64 GetTotalFilesAndDirs() const
{
- for (unsigned i = 0; i < kHashSize; i++)
- if (Hash[i] != 0)
- return true;
- return Id != 0;
+ UInt64 sum = 0;
+ FOR_VECTOR (i, Images)
+ sum += Images[i].GetTotalFilesAndDirs();
+ return sum;
}
+
+ void ToUnicode(UString &s);
+ bool Parse();
+};
+
+struct CVolume
+{
+ CHeader Header;
+ CMyComPtr<IInStream> Stream;
};
class CDatabase
{
- const Byte *DirData;
+ 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);
+ HRESULT ParseImageDirs(CByteBuffer &buf, int parent);
public:
- CRecordVector<CStreamInfo> Streams;
- CObjectVector<CItem> Items;
- CIntVector SortedItems;
- int NumImages;
- bool SkipRoot;
- bool ShowImageNumber;
+ CRecordVector<CStreamInfo> DataStreams;
+
+ CRecordVector<CStreamInfo> MetaStreams;
+
+ CRecordVector<CItem> Items;
+ CObjectVector<CByteBuffer> ReparseItems;
+ CIntVector ItemToReparse; // from index_in_Items to index_in_ReparseItems
+ // -1 means no reparse;
+
+ CObjectVector<CImage> Images;
+
bool IsOldVersion;
+ bool ThereAreDeletedStreams;
+ bool ThereAreAltStreams;
+ bool RefCountError;
+
+ // User Items can contain all images or just one image from all.
+ CUIntVector SortedItems;
+ int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items
+
+ unsigned NumExludededItems;
+ int ExludedItem; // -1 : if there are no exclude items
+ CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives
+
+ bool ThereIsError() const { return RefCountError; }
+
+ unsigned GetNumUserItemsInImage(unsigned imageIndex) const
+ {
+ if (IndexOfUserImage >= 0 && imageIndex != (unsigned)IndexOfUserImage)
+ return 0;
+ if (imageIndex >= Images.Size())
+ return 0;
+ return Images[imageIndex].NumItems - NumExludededItems;
+ }
+
+ bool ItemHasStream(const CItem &item) const;
UInt64 GetUnpackSize() const
{
UInt64 res = 0;
- for (int i = 0; i < Streams.Size(); i++)
- res += Streams[i].Resource.UnpackSize;
+ FOR_VECTOR (i, DataStreams)
+ res += DataStreams[i].Resource.UnpackSize;
return res;
}
UInt64 GetPackSize() const
{
UInt64 res = 0;
- for (int i = 0; i < Streams.Size(); i++)
- res += Streams[i].Resource.PackSize;
+ FOR_VECTOR (i, DataStreams)
+ res += DataStreams[i].Resource.PackSize;
return res;
}
void Clear()
{
- Streams.Clear();
+ DataStreams.Clear();
+
+ MetaStreams.Clear();
+
Items.Clear();
+ ReparseItems.Clear();
+ ItemToReparse.Clear();
+
SortedItems.Clear();
- NumImages = 0;
+
+ Images.Clear();
+ VirtualRoots.Clear();
- SkipRoot = true;
- ShowImageNumber = true;
IsOldVersion = false;
+ ThereAreDeletedStreams = false;
+ ThereAreAltStreams = false;
+ RefCountError = false;
}
- UString GetItemPath(int index) const;
+ CDatabase(): RefCountError(false) {}
- HRESULT Open(IInStream *inStream, const CHeader &h, CByteBuffer &xml, IArchiveOpenCallback *openCallback);
+ void GetShortName(unsigned index, NWindows::NCOM::CPropVariant &res) const;
+ void GetItemName(unsigned index1, NWindows::NCOM::CPropVariant &res) const;
+ void GetItemPath(unsigned index, bool showImageNumber, NWindows::NCOM::CPropVariant &res) const;
- void DetectPathMode()
- {
- ShowImageNumber = (NumImages != 1);
- }
+ HRESULT OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml);
+ HRESULT Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback);
+ HRESULT FillAndCheck();
- HRESULT Sort(bool skipRootDir);
+ /*
+ imageIndex showImageNumber NumImages
+ * true * Show Image_Number
+ -1 * >1 Show Image_Number
+ -1 false 1 Don't show Image_Number
+ N false * Don't show Image_Number
+ */
+ HRESULT GenerateSortedItems(int imageIndex, bool showImageNumber);
+
+ HRESULT ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback);
};
-HRESULT ReadHeader(IInStream *inStream, CHeader &header);
+HRESULT ReadHeader(IInStream *inStream, CHeader &header, UInt64 &phySize);
class CUnpacker
{
@@ -285,6 +495,7 @@ class CUnpacker
NXpress::CDecoder xpressDecoder;
CByteBuffer sizesBuf;
+
HRESULT Unpack(IInStream *inStream, const CResource &res, bool lzxMode,
ISequentialOutStream *outStream, ICompressProgressInfo *progress);
public: