This commit is contained in:
Igor Pavlov
2014-11-23 00:00:00 +00:00
committed by Kornel Lesiński
parent 83f8ddcc5b
commit f08f4dcc3c
1158 changed files with 76451 additions and 35082 deletions

2
CPP/7zip/Archive/Wim/StdAfx.h Executable file → Normal file
View File

@@ -3,6 +3,6 @@
#ifndef __STDAFX_H
#define __STDAFX_H
#include "../../../Common/MyWindows.h"
#include "../../../Common/Common.h"
#endif

823
CPP/7zip/Archive/Wim/WimHandler.cpp Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

99
CPP/7zip/Archive/Wim/WimHandler.h Executable file → Normal file
View File

@@ -3,72 +3,75 @@
#ifndef __ARCHIVE_WIM_HANDLER_H
#define __ARCHIVE_WIM_HANDLER_H
#include "Common/MyCom.h"
#include "Common/MyXml.h"
#include "../../../Common/MyCom.h"
#include "WimIn.h"
namespace NArchive {
namespace NWim {
struct CVolume
{
CHeader Header;
CMyComPtr<IInStream> Stream;
};
struct CImageInfo
{
bool CTimeDefined;
bool MTimeDefined;
bool NameDefined;
// bool IndexDefined;
FILETIME CTime;
FILETIME MTime;
UString Name;
// UInt32 Index;
CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false)
// , IndexDefined(false)
{}
void Parse(const CXmlItem &item);
};
struct CXml
{
CByteBuffer Data;
UInt16 VolIndex;
CObjectVector<CImageInfo> Images;
void ToUnicode(UString &s);
void Parse();
};
class CHandler:
public IInArchive,
public IArchiveGetRawProps,
public IArchiveGetRootProps,
public IArchiveKeepModeForNextOpen,
public ISetProperties,
public IOutArchive,
public CMyUnknownImp
{
CDatabase _db;
UInt32 _version;
bool _isOldVersion;
UInt32 _bootIndex;
CObjectVector<CVolume> _volumes;
CObjectVector<CXml> _xmls;
int _nameLenForStreams;
CObjectVector<CWimXml> _xmls;
// unsigned _nameLenForStreams;
bool _xmlInComments;
unsigned _numXmlItems;
unsigned _numIgnoreItems;
bool _xmlError;
bool _isArc;
bool _set_use_ShowImageNumber;
bool _set_showImageNumber;
int _defaultImageNumber;
bool _showImageNumber;
bool _keepMode_ShowImageNumber;
UInt64 _phySize;
int _firstVolumeIndex;
void InitDefaults()
{
_set_use_ShowImageNumber = false;
_set_showImageNumber = false;
_defaultImageNumber = -1;
}
bool ThereIsError() const { return _xmlError || _db.ThereIsError(); }
HRESULT GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType);
HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);
HRESULT GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft);
public:
MY_UNKNOWN_IMP1(IInArchive)
CHandler();
MY_UNKNOWN_IMP6(
IInArchive,
IArchiveGetRawProps,
IArchiveGetRootProps,
IArchiveKeepModeForNextOpen,
ISetProperties,
IOutArchive)
INTERFACE_IInArchive(;)
};
class COutHandler:
public IOutArchive,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IOutArchive)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
STDMETHOD(KeepModeForNextOpen)();
INTERFACE_IOutArchive(;)
};

1805
CPP/7zip/Archive/Wim/WimHandlerOut.cpp Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

1111
CPP/7zip/Archive/Wim/WimIn.cpp Executable file → Normal file
View File

File diff suppressed because it is too large Load Diff

355
CPP/7zip/Archive/Wim/WimIn.h Executable file → Normal file
View File

@@ -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:

23
CPP/7zip/Archive/Wim/WimRegister.cpp Executable file → Normal file
View File

@@ -5,14 +5,23 @@
#include "../../Common/RegisterArc.h"
#include "WimHandler.h"
static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
#ifndef EXTRACT_ONLY
static IOutArchive *CreateArcOut() { return new NArchive::NWim::COutHandler; }
#else
#define CreateArcOut 0
#endif
namespace NArchive {
namespace NWim {
IMP_CreateArcIn
IMP_CreateArcOut
static CArcInfo g_ArcInfo =
{ L"wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, CreateArcOut };
{ "wim", "wim swm", 0, 0xE6,
8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 },
0,
NArcInfoFlags::kAltStreams |
NArcInfoFlags::kNtSecure |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks
, REF_CreateArc_Pair };
REGISTER_ARC(Wim)
}}