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
path: root/CPP
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-07-11 04:00:00 +0400
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:52 +0300
commit7038848692e7049234f223703522681a19db49a5 (patch)
tree38c5acef39a775a1f58f81b13be81fc6ef8c72e3 /CPP
parentfd8b1d78b496fe38193bf8c5e86af3b43f0b022d (diff)
4.49 beta
Diffstat (limited to 'CPP')
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixerMT.cpp6
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixerMT.h2
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.cpp4
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.h17
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithSha1.cpp24
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithSha1.h38
-rwxr-xr-xCPP/7zip/Archive/Wim/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandler.cpp477
-rwxr-xr-xCPP/7zip/Archive/Wim/WimHandler.h60
-rwxr-xr-xCPP/7zip/Archive/Wim/WimIn.cpp467
-rwxr-xr-xCPP/7zip/Archive/Wim/WimIn.h139
-rwxr-xr-xCPP/7zip/Archive/Wim/WimRegister.cpp13
-rwxr-xr-xCPP/7zip/Archive/Wim/wim.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Bundles/Format7zF/Format7z.dsp60
-rwxr-xr-xCPP/7zip/Bundles/Format7zF/makefile9
-rwxr-xr-xCPP/7zip/Bundles/Format7zF/resource.rc3
-rwxr-xr-xCPP/7zip/Common/FilterCoder.cpp6
-rwxr-xr-xCPP/7zip/Common/FilterCoder.h5
-rwxr-xr-xCPP/7zip/Common/InMemStream.h2
-rwxr-xr-xCPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp2
-rwxr-xr-xCPP/7zip/Compress/Lzx/LzxDecoder.cpp31
-rwxr-xr-xCPP/7zip/Compress/Lzx/LzxDecoder.h4
-rwxr-xr-xCPP/7zip/Crypto/Hash/RandGen.cpp37
-rwxr-xr-xCPP/7zip/Guid.txt1
-rwxr-xr-xCPP/7zip/MyVersion.h8
-rwxr-xr-xCPP/7zip/UI/Common/ExtractingFilePath.cpp17
-rwxr-xr-xCPP/7zip/UI/Common/LoadCodecs.cpp6
-rwxr-xr-xCPP/7zip/UI/Console/List.cpp30
-rwxr-xr-xCPP/7zip/UI/Far/ExtractEngine.cpp7
-rwxr-xr-xCPP/7zip/UI/Far/OverwriteDialog.cpp19
-rwxr-xr-xCPP/7zip/UI/Far/OverwriteDialog.h1
-rwxr-xr-xCPP/7zip/UI/Far/PluginWrite.cpp77
-rwxr-xr-xCPP/Common/Buffer.h2
-rwxr-xr-xCPP/Common/IntToString.cpp2
-rwxr-xr-xCPP/Windows/FileName.cpp63
-rwxr-xr-xCPP/Windows/FileName.h20
36 files changed, 1527 insertions, 140 deletions
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.cpp b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
index ad6e12d8..ad32896c 100755
--- a/CPP/7zip/Archive/Common/CoderMixerMT.cpp
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.cpp
@@ -45,11 +45,11 @@ STDMETHODIMP CCoderMixerMT::Code(ISequentialInStream *inStream,
RINOK(_coders[i].Create());
}
- while (_streamBinders.Size() + 1 < _coders.Size())
+ _streamBinders.Clear();
+ for (i = 0; i + 1 < _coders.Size(); i++)
{
_streamBinders.Add(CStreamBinder());
- int i = _streamBinders.Size() - 1;
- CStreamBinder &sb = _streamBinders.Back();
+ CStreamBinder &sb = _streamBinders[i];
RINOK(sb.CreateEvents());
sb.CreateStreams(&_coders[i + 1].InStream, &_coders[i].OutStream);
}
diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h
index a2250e8a..88b6e3e6 100755
--- a/CPP/7zip/Archive/Common/CoderMixerMT.h
+++ b/CPP/7zip/Archive/Common/CoderMixerMT.h
@@ -3,7 +3,7 @@
#ifndef __CODER_MIXER_MT_H
#define __CODER_MIXER_MT_H
-#include "../../../Common/Vector.h"
+#include "../../../Common/MyVector.h"
#include "../../../Common/MyCom.h"
#include "../../ICoder.h"
#include "../../Common/StreamBinder.h"
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
index 43166ee1..2ab2da66 100755
--- a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
@@ -4,7 +4,7 @@
#include "OutStreamWithCRC.h"
-STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 realProcessedSize;
HRESULT result;
@@ -15,7 +15,7 @@ STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *pr
}
else
result = _stream->Write(data, size, &realProcessedSize);
- if (_calculateCrc)
+ if (_calculate)
_crc = CrcUpdate(_crc, data, realProcessedSize);
_size += realProcessedSize;
if(processedSize != NULL)
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
index a8791288..eaeecde7 100755
--- a/CPP/7zip/Archive/Common/OutStreamWithCRC.h
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
@@ -15,27 +15,24 @@ class COutStreamWithCRC:
public ISequentialOutStream,
public CMyUnknownImp
{
-public:
- MY_UNKNOWN_IMP
-
- STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
-private:
CMyComPtr<ISequentialOutStream> _stream;
UInt64 _size;
UInt32 _crc;
- bool _calculateCrc;
+ bool _calculate;
public:
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
void SetStream(ISequentialOutStream *stream) { _stream = stream; }
- void Init(bool calculateCrc = true)
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
{
_size = 0;
- _calculateCrc = calculateCrc;
+ _calculate = calculate;
_crc = CRC_INIT_VAL;
}
- void ReleaseStream() { _stream.Release(); }
+ void InitCRC() { _crc = CRC_INIT_VAL; }
UInt64 GetSize() const { return _size; }
UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }
- void InitCRC() { _crc = CRC_INIT_VAL; }
};
#endif
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
new file mode 100755
index 00000000..51d2568a
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp
@@ -0,0 +1,24 @@
+// OutStreamWithSha1.cpp
+
+#include "StdAfx.h"
+
+#include "OutStreamWithSha1.h"
+
+STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result;
+ if(!_stream)
+ {
+ realProcessedSize = size;
+ result = S_OK;
+ }
+ else
+ result = _stream->Write(data, size, &realProcessedSize);
+ if (_calculate)
+ _sha.Update((const Byte *)data, realProcessedSize);
+ _size += realProcessedSize;
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
new file mode 100755
index 00000000..976b347c
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h
@@ -0,0 +1,38 @@
+// OutStreamWithSha1.h
+
+#ifndef __OUTSTREAMWITHSHA1_H
+#define __OUTSTREAMWITHSHA1_H
+
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+
+
+#include "../../Crypto/Hash/Sha1.h"
+
+
+class COutStreamWithSha1:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ NCrypto::NSha1::CContext _sha;
+ bool _calculate;
+public:
+ MY_UNKNOWN_IMP
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void ReleaseStream() { _stream.Release(); }
+ void Init(bool calculate = true)
+ {
+ _size = 0;
+ _calculate = calculate;
+ _sha.Init();
+ }
+ void InitSha1() { _sha.Init(); }
+ UInt64 GetSize() const { return _size; }
+ void Final(Byte *digest) { _sha.Final(digest); }
+};
+
+#endif
diff --git a/CPP/7zip/Archive/Wim/StdAfx.h b/CPP/7zip/Archive/Wim/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/StdAfx.h
@@ -0,0 +1,8 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+
+#endif
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
new file mode 100755
index 00000000..aa9300a2
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -0,0 +1,477 @@
+// WimHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/IntToString.h"
+#include "Common/Defs.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Common/StreamUtils.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "WimHandler.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NWim {
+
+#define WIM_DETAILS
+
+#ifdef WIM_DETAILS
+
+enum
+{
+ kpidVolume = kpidUserDefined,
+ kpidOffset,
+ kpidLinks
+};
+
+#endif
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidAttributes, VT_UI8},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidCreationTime, VT_FILETIME},
+ { NULL, kpidLastAccessTime, VT_FILETIME},
+ { NULL, kpidLastWriteTime, VT_FILETIME}
+
+ #ifdef WIM_DETAILS
+ , { L"Volume", kpidVolume, VT_UI4}
+ , { L"Offset", kpidOffset, VT_UI8}
+ , { L"Links", kpidLinks, VT_UI4}
+ #endif
+};
+
+static const wchar_t *kStreamsNamePrefix = L"Files" WSTRING_PATH_SEPARATOR;
+static const wchar_t *kMethodLZX = L"LZX";
+static const wchar_t *kMethodCopy = L"Copy";
+
+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 (index < (UInt32)m_Database.Items.Size())
+ {
+ const CItem &item = m_Database.Items[index];
+ const CStreamInfo *si = NULL;
+ if (item.StreamIndex >= 0)
+ si = &m_Database.Streams[item.StreamIndex];
+
+ switch(propID)
+ {
+ case kpidPath:
+ if (item.HasMetadata)
+ propVariant = item.Name;
+ else
+ {
+ wchar_t sz[32];
+ ConvertUInt64ToString(item.StreamIndex, sz);
+ UString s = sz;
+ while (s.Length() < m_NameLenForStreams)
+ s = L'0' + s;
+ s = UString(kStreamsNamePrefix) + s;
+ propVariant = s;
+ break;
+ }
+ break;
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidAttributes:
+ if (item.HasMetadata)
+ propVariant = item.Attributes;
+ break;
+ case kpidCreationTime:
+ if (item.HasMetadata)
+ propVariant = item.CreationTime;
+ break;
+ case kpidLastAccessTime:
+ if (item.HasMetadata)
+ propVariant = item.LastAccessTime;
+ break;
+ case kpidLastWriteTime:
+ if (item.HasMetadata)
+ propVariant = item.LastWriteTime;
+ break;
+ case kpidPackedSize:
+ if (si)
+ propVariant = si->Resource.PackSize;
+ else
+ propVariant = (UInt64)0;
+ break;
+ case kpidSize:
+ if (si)
+ propVariant = si->Resource.UnpackSize;
+ else
+ propVariant = (UInt64)0;
+ break;
+ case kpidMethod:
+ if (si)
+ if (si->Resource.IsCompressed())
+ propVariant = kMethodLZX;
+ else
+ propVariant = kMethodCopy;
+ break;
+ #ifdef WIM_DETAILS
+ case kpidVolume:
+ if (si)
+ propVariant = (UInt32)si->PartNumber;
+ break;
+ case kpidOffset:
+ if (si)
+ propVariant = (UInt64)si->Resource.Offset;
+ break;
+ case kpidLinks:
+ if (si)
+ propVariant = (UInt32)si->RefCount;
+ else
+ propVariant = (UInt64)0;
+ break;
+ #endif
+ }
+ }
+ else
+ {
+ index -= m_Database.Items.Size();
+ {
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ wchar_t sz[32];
+ ConvertUInt64ToString(m_Xmls[index].VolIndex, sz);
+ UString s = (UString)sz + L".xml";
+ propVariant = s;
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidPackedSize:
+ case kpidSize:
+ propVariant = (UInt64)m_Xmls[index].Data.GetCapacity();
+ break;
+ case kpidMethod:
+ propVariant = L"Copy";
+ break;
+ }
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+class CVolumeName
+{
+ // UInt32 _volIndex;
+ UString _before;
+ UString _after;
+public:
+ CVolumeName() {};
+
+ void InitName(const UString &name)
+ {
+ // _volIndex = 1;
+ int dotPos = name.ReverseFind('.');
+ if (dotPos < 0)
+ dotPos = name.Length();
+ _before = name.Left(dotPos);
+ _after = name.Mid(dotPos);
+ }
+
+ UString GetNextName(UInt32 index)
+ {
+ wchar_t s[32];
+ ConvertUInt64ToString((index), s);
+ return _before + (UString)s + _after;
+ }
+};
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ try
+ {
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+
+ CVolumeName seqName;
+ if (openArchiveCallback != NULL)
+ openArchiveCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);
+
+ UInt32 numVolumes = 1;
+ int firstVolumeIndex = -1;
+ for (UInt32 i = 1; i <= numVolumes; i++)
+ {
+ CMyComPtr<IInStream> curStream;
+ if (i != 1)
+ {
+ UString fullName = seqName.GetNextName(i);
+ HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);
+ if (result == S_FALSE)
+ continue;
+ if (result != S_OK)
+ return result;
+ if (!curStream)
+ break;
+ }
+ else
+ curStream = inStream;
+ CHeader header;
+ HRESULT res = NWim::ReadHeader(curStream, header);
+ if (res != S_OK)
+ {
+ if (i == 1)
+ return res;
+ if (res == S_FALSE)
+ continue;
+ return res;
+ }
+ if (firstVolumeIndex >= 0)
+ if (!header.AreFromOnArchive(m_Volumes[firstVolumeIndex].Header))
+ break;
+ if (m_Volumes.Size() > header.PartNumber && m_Volumes[header.PartNumber].Stream)
+ break;
+ CXml xml;
+ xml.VolIndex = header.PartNumber;
+ res = OpenArchive(curStream, header, xml.Data, m_Database);
+ if (res != S_OK)
+ {
+ if (i == 1)
+ return res;
+ if (res == S_FALSE)
+ continue;
+ return res;
+ }
+
+ while (m_Volumes.Size() <= header.PartNumber)
+ m_Volumes.Add(CVolume());
+ CVolume &volume = m_Volumes[header.PartNumber];
+ volume.Header = header;
+ volume.Stream = curStream;
+
+ firstVolumeIndex = header.PartNumber;
+
+ bool needAddXml = true;
+ if (m_Xmls.Size() != 0)
+ if (xml.Data == m_Xmls[0].Data)
+ needAddXml = false;
+ if (needAddXml)
+ m_Xmls.Add(xml);
+
+ if (i == 1)
+ {
+ if (header.PartNumber != 1)
+ break;
+ if (!openVolumeCallback)
+ break;
+ numVolumes = header.NumParts;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));
+ if (propVariant.vt != VT_BSTR)
+ break;
+ seqName.InitName(propVariant.bstrVal);
+ }
+ }
+ }
+
+ RINOK(SortDatabase(m_Database));
+
+ wchar_t sz[32];
+ ConvertUInt64ToString(m_Database.Streams.Size(), sz);
+ m_NameLenForStreams = MyStringLen(sz);
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_Database.Clear();
+ m_Volumes.Clear();
+ m_Xmls.Clear();
+ m_NameLenForStreams = 0;
+ 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.Items.Size() + m_Xmls.Size();
+ if (numItems == 0)
+ return S_OK;
+ bool testMode = (_aTestMode != 0);
+
+ UInt32 i;
+ UInt64 totalSize = 0;
+ for (i = 0; i < numItems; i++)
+ {
+ UInt32 index = allFilesMode ? i : indices[i];
+ if (index < (UInt32)m_Database.Items.Size())
+ {
+ int streamIndex = m_Database.Items[index].StreamIndex;
+ if (streamIndex >= 0)
+ {
+ const CStreamInfo &si = m_Database.Streams[streamIndex];
+ totalSize += si.Resource.UnpackSize;
+ }
+ }
+ else
+ totalSize += m_Xmls[index - (UInt32)m_Database.Items.Size()].Data.GetCapacity();
+ }
+
+ RINOK(extractCallback->SetTotal(totalSize));
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize = 0;
+
+ int prevSuccessStreamIndex = -1;
+
+ CUnpacker unpacker;
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+
+ for (i = 0; i < numItems; currentTotalSize += currentItemSize)
+ {
+ currentItemSize = 0;
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ UInt32 index = allFilesMode ? i : indices[i];
+ i++;
+ Int32 askMode = testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ if (index >= (UInt32)m_Database.Items.Size())
+ {
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ const CByteBuffer &data = m_Xmls[index - (UInt32)m_Database.Items.Size()].Data;
+ currentItemSize = data.GetCapacity();
+ if (realOutStream)
+ {
+ RINOK(WriteStream(realOutStream, (const Byte *)data, (UInt32)data.GetCapacity(), NULL));
+ realOutStream.Release();
+ }
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ const CItem &item = m_Database.Items[index];
+ int streamIndex = item.StreamIndex;
+ if (streamIndex < 0)
+ {
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(item.HasStream() ?
+ NArchive::NExtract::NOperationResult::kDataError :
+ NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ const CStreamInfo &si = m_Database.Streams[streamIndex];
+ currentItemSize = si.Resource.UnpackSize;
+
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ Int32 opRes = NArchive::NExtract::NOperationResult::kOK;
+ if (streamIndex != prevSuccessStreamIndex || realOutStream)
+ {
+ Byte digest[20];
+ localCompressProgressSpec->Init(progress, &currentTotalSize, &currentTotalSize);
+ HRESULT res = unpacker.Unpack(m_Volumes[si.PartNumber].Stream, si.Resource, realOutStream, compressProgress, digest);
+ if (res == S_OK)
+ {
+ if (memcmp(digest, si.Hash, kHashSize) == 0)
+ prevSuccessStreamIndex = streamIndex;
+ else
+ opRes = NArchive::NExtract::NOperationResult::kCRCError;
+ }
+ else if (res == S_FALSE)
+ opRes = NArchive::NExtract::NOperationResult::kDataError;
+ else
+ return res;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(opRes));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = m_Database.Items.Size() + m_Xmls.Size();
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
new file mode 100755
index 00000000..5142d785
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -0,0 +1,60 @@
+// WimHandler.h
+
+#ifndef __ARCHIVE_WIM_HANDLER_H
+#define __ARCHIVE_WIM_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "WimIn.h"
+
+namespace NArchive {
+namespace NWim {
+
+struct CVolume
+{
+ CHeader Header;
+ CMyComPtr<IInStream> Stream;
+};
+
+struct CXml
+{
+ CByteBuffer Data;
+ UInt16 VolIndex;
+};
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IInArchive)
+
+ 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:
+ CDatabase m_Database;
+ CObjectVector<CVolume> m_Volumes;
+ CObjectVector<CXml> m_Xmls;
+ int m_NameLenForStreams;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
new file mode 100755
index 00000000..e99cb37b
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -0,0 +1,467 @@
+// Archive/WimIn.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyCom.h"
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../Common/OutStreamWithSha1.h"
+
+#include "WimIn.h"
+
+namespace NArchive{
+namespace NWim{
+
+static const int kChunkSizeBits = 15;
+static const UInt32 kChunkSize = (1 << kChunkSizeBits);
+
+static HRESULT ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ RINOK(ReadStream(inStream, data, size, &realProcessedSize));
+ return (realProcessedSize == size) ? S_OK : S_FALSE;
+}
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
+#define WIM_LITTLE_ENDIAN_UNALIGN
+#endif
+
+#ifdef WIM_LITTLE_ENDIAN_UNALIGN
+static inline UInt16 GetUInt16FromMem(const Byte *p) { return *(const UInt16 *)p; }
+static inline UInt32 GetUInt32FromMem(const Byte *p) { return *(const UInt32 *)p; }
+static inline UInt64 GetUInt64FromMem(const Byte *p) { return *(const UInt64 *)p; }
+#else
+static UInt16 GetUInt16FromMem(const Byte *p) { return p[0] | ((UInt16)p[1] << 8); }
+static UInt32 GetUInt32FromMem(const Byte *p) { return p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24); }
+static UInt64 GetUInt64FromMem(const Byte *p) { return GetUInt32FromMem(p) | ((UInt64)GetUInt32FromMem(p + 4) << 32); }
+#endif
+
+static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
+{
+ ft->dwLowDateTime = GetUInt32FromMem(p);
+ ft->dwHighDateTime = GetUInt32FromMem(p + 4);
+}
+
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ RINOK(inStream->Seek(resource.Offset, STREAM_SEEK_SET, NULL));
+
+ CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream();
+ CMyComPtr<ISequentialInStream> limitedStream = limitedStreamSpec;
+ limitedStreamSpec->SetStream(inStream);
+
+ if (!copyCoder)
+ {
+ copyCoderSpec = new NCompress::CCopyCoder;
+ copyCoder = copyCoderSpec;
+ }
+ if (!resource.IsCompressed())
+ {
+ if (resource.PackSize != resource.UnpackSize)
+ return S_FALSE;
+ limitedStreamSpec->Init(resource.PackSize);
+ return copyCoder->Code(limitedStreamSpec, outStream, NULL, NULL, progress);
+ }
+ if (resource.UnpackSize == 0)
+ return S_OK;
+ UInt64 numChunks = (resource.UnpackSize + kChunkSize - 1) >> kChunkSizeBits;
+ unsigned entrySize = ((resource.UnpackSize > (UInt64)1 << 32) ? 8 : 4);
+ UInt64 sizesBufSize64 = entrySize * (numChunks - 1);
+ UInt32 sizesBufSize = (UInt32)sizesBufSize64;
+ if (sizesBufSize != sizesBufSize64)
+ return E_OUTOFMEMORY;
+ if (sizesBufSize > sizesBuf.GetCapacity())
+ {
+ sizesBuf.Free();
+ sizesBuf.SetCapacity(sizesBufSize);
+ }
+ RINOK(ReadBytes(inStream, (Byte *)sizesBuf, sizesBufSize));
+ const Byte *p = (const Byte *)sizesBuf;
+
+ if (!lzxDecoder)
+ {
+ lzxDecoderSpec = new NCompress::NLzx::CDecoder(true);
+ lzxDecoder = lzxDecoderSpec;
+ RINOK(lzxDecoderSpec->SetParams(kChunkSizeBits));
+ }
+
+ UInt64 baseOffset = resource.Offset + sizesBufSize64;
+ UInt64 outProcessed = 0;
+ for (UInt32 i = 0; i < (UInt32)numChunks; i++)
+ {
+ UInt64 offset = 0;
+ if (i > 0)
+ {
+ if (entrySize == 4)
+ offset = GetUInt32FromMem(p);
+ else
+ offset = GetUInt64FromMem(p);
+ p += entrySize;
+ }
+ UInt64 nextOffset = resource.PackSize - sizesBufSize64;
+ if (i + 1 < (UInt32)numChunks)
+ if (entrySize == 4)
+ nextOffset = GetUInt32FromMem(p);
+ else
+ nextOffset = GetUInt64FromMem(p);
+ if (nextOffset < offset)
+ return S_FALSE;
+
+ RINOK(inStream->Seek(baseOffset + offset, STREAM_SEEK_SET, NULL));
+ UInt64 inSize = nextOffset - offset;
+ limitedStreamSpec->Init(inSize);
+
+ if (progress)
+ {
+ RINOK(progress->SetRatioInfo(&offset, &outProcessed));
+ }
+
+ UInt32 outSize = kChunkSize;
+ if (outProcessed + outSize > resource.UnpackSize)
+ outSize = (UInt32)(resource.UnpackSize - outProcessed);
+ UInt64 outSize64 = outSize;
+ lzxDecoderSpec->SetKeepHistory(false, 0);
+ ICompressCoder *coder = (inSize == outSize) ? copyCoder : lzxDecoder;
+ RINOK(coder->Code(limitedStreamSpec, outStream, NULL, &outSize64, NULL));
+ outProcessed += outSize;
+ }
+ return S_OK;
+}
+
+HRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)
+{
+ COutStreamWithSha1 *shaStreamSpec = new COutStreamWithSha1();
+ CMyComPtr<ISequentialOutStream> shaStream = shaStreamSpec;
+ shaStreamSpec->SetStream(outStream);
+ shaStreamSpec->Init(digest != NULL);
+ HRESULT result = Unpack(inStream, resource, shaStream, progress);
+ if (digest)
+ shaStreamSpec->Final(digest);
+ return result;
+}
+
+static HRESULT UnpackData(IInStream *inStream, const CResource &resource, CByteBuffer &buf, Byte *digest)
+{
+ size_t size = (size_t)resource.UnpackSize;
+ if (size != resource.UnpackSize)
+ return E_OUTOFMEMORY;
+ buf.Free();
+ buf.SetCapacity(size);
+
+ CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2();
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ outStreamSpec->Init((Byte *)buf, size);
+
+ CUnpacker unpacker;
+ return unpacker.Unpack(inStream, resource, outStream, NULL, digest);
+}
+
+static const UInt32 kSignatureSize = 8;
+static const Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };
+
+static void GetResource(const Byte *p, CResource &res)
+{
+ res.Flags = p[7];
+ res.PackSize = GetUInt64FromMem(p) & (((UInt64)1 << 56) - 1);
+ res.Offset = GetUInt64FromMem(p + 8);
+ res.UnpackSize = GetUInt64FromMem(p + 16);
+}
+
+static void GetStream(const Byte *p, CStreamInfo &s)
+{
+ GetResource(p, s.Resource);
+ s.PartNumber = GetUInt16FromMem(p + 24);
+ s.RefCount = GetUInt32FromMem(p + 26);
+ memcpy(s.Hash, p + 30, kHashSize);
+}
+
+static HRESULT ParseDirItem(const Byte *base, size_t pos, size_t size,
+ const UString &prefix, CObjectVector<CItem> &items)
+{
+ for (;;)
+ {
+ if (pos + 8 > size)
+ return S_FALSE;
+ const Byte *p = base + pos;
+ UInt64 length = GetUInt64FromMem(p);
+ if (length == 0)
+ return S_OK;
+ if (pos + 102 > size || pos + length + 8 > size || length > ((UInt64)1 << 62))
+ return S_FALSE;
+ CItem item;
+ item.Attributes = GetUInt32FromMem(p + 8);
+ // item.SecurityId = GetUInt32FromMem(p + 0xC);
+ UInt64 subdirOffset = GetUInt64FromMem(p + 0x10);
+ GetFileTimeFromMem(p + 0x28, &item.CreationTime);
+ GetFileTimeFromMem(p + 0x30, &item.LastAccessTime);
+ GetFileTimeFromMem(p + 0x38, &item.LastWriteTime);
+ memcpy(item.Hash, p + 0x40, kHashSize);
+
+ // UInt16 shortNameLen = GetUInt16FromMem(p + 98);
+ UInt16 fileNameLen = GetUInt16FromMem(p + 100);
+
+ size_t tempPos = pos + 102;
+ if (tempPos + fileNameLen > size)
+ return S_FALSE;
+
+ wchar_t *sz = item.Name.GetBuffer(prefix.Length() + fileNameLen / 2 + 1);
+ MyStringCopy(sz, (const wchar_t *)prefix);
+ sz += prefix.Length();
+ for (UInt16 i = 0; i + 2 <= fileNameLen; i += 2)
+ *sz++ = GetUInt16FromMem(base + tempPos + i);
+ *sz++ = '\0';
+ item.Name.ReleaseBuffer();
+ if (fileNameLen == 0 && item.IsDirectory() && !item.HasStream())
+ {
+ item.Attributes = 0x10; // some swm archives have system/hidden attributes for root
+ item.Name.Delete(item.Name.Length() - 1);
+ }
+ items.Add(item);
+ pos += (size_t)length;
+ if (item.IsDirectory() && (subdirOffset != 0))
+ {
+ if (subdirOffset >= size)
+ return S_FALSE;
+ RINOK(ParseDirItem(base, (size_t)subdirOffset, size, item.Name + WCHAR_PATH_SEPARATOR, items));
+ }
+ }
+}
+
+static HRESULT ParseDir(const Byte *base, size_t size,
+ const UString &prefix, CObjectVector<CItem> &items)
+{
+ size_t pos = 0;
+ if (pos + 8 > size)
+ return S_FALSE;
+ const Byte *p = base + pos;
+ UInt32 totalLength = GetUInt32FromMem(p);
+ // UInt32 numEntries = GetUInt32FromMem(p + 4);
+ pos += 8;
+ {
+ /*
+ CRecordVector<UInt64> entryLens;
+ UInt64 sum = 0;
+ for (UInt32 i = 0; i < numEntries; i++)
+ {
+ if (pos + 8 > size)
+ return S_FALSE;
+ UInt64 len = GetUInt64FromMem(p + pos);
+ entryLens.Add(len);
+ sum += len;
+ pos += 8;
+ }
+ pos += sum; // skeep security descriptors
+ while ((pos & 7) != 0)
+ pos++;
+ if (pos != totalLength)
+ return S_FALSE;
+ */
+ pos = totalLength;
+ }
+ return ParseDirItem(base, pos, size, prefix, items);
+}
+
+static int CompareHashRefs(const int *p1, const int *p2, void *param)
+{
+ const CRecordVector<CStreamInfo> &streams = *(const CRecordVector<CStreamInfo> *)param;
+ return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);
+}
+
+static int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)
+{
+ int res = MyCompare(p1->PartNumber, p2->PartNumber);
+ if (res != 0)
+ return res;
+ return MyCompare(p1->Resource.Offset, p2->Resource.Offset);
+}
+
+int CompareItems(void *const *a1, void *const *a2, void * /* param */)
+{
+ const CItem &i1 = **((const CItem **)a1);
+ const CItem &i2 = **((const CItem **)a2);
+
+ if (i1.IsDirectory() != i2.IsDirectory())
+ return (i1.IsDirectory()) ? 1 : -1;
+ if (i1.IsDirectory())
+ return -MyStringCompareNoCase(i1.Name, i2.Name);
+
+ int res = MyCompare(i1.StreamIndex, i2.StreamIndex);
+ if (res != 0)
+ return res;
+ return MyStringCompareNoCase(i1.Name, i2.Name);
+}
+
+static int FindHash(const CRecordVector<CStreamInfo> &streams,
+ const CRecordVector<int> &sortedByHash, const Byte *hash)
+{
+ int left = 0, right = streams.Size();
+ while (left != right)
+ {
+ int mid = (left + right) / 2;
+ int streamIndex = sortedByHash[mid];
+ UInt32 i;
+ const Byte *hash2 = streams[streamIndex].Hash;
+ for (i = 0; i < kHashSize; i++)
+ if (hash[i] != hash2[i])
+ break;
+ if (i == kHashSize)
+ return streamIndex;
+ if (hash[i] < hash2[i])
+ right = mid;
+ else
+ left = mid + 1;
+ }
+ return -1;
+}
+
+HRESULT ReadHeader(IInStream *inStream, CHeader &h)
+{
+ const UInt32 kHeaderSizeMax = 0xD0;
+ Byte p[kHeaderSizeMax];
+ RINOK(ReadBytes(inStream, p, kHeaderSizeMax));
+ UInt32 haderSize = GetUInt32FromMem(p + 8);
+ if (memcmp(p, kSignature, kSignatureSize) != 0)
+ return S_FALSE;
+ if (haderSize < 0x74)
+ return S_FALSE;
+ h.Version = GetUInt32FromMem(p + 0x0C);
+ h.Flags = GetUInt32FromMem(p + 0x10);
+ if (!h.IsSupported())
+ return S_FALSE;
+ if (GetUInt32FromMem(p + 0x14) != kChunkSize)
+ return S_FALSE;
+ memcpy(h.Guid, p + 0x18, 16);
+ h.PartNumber = GetUInt16FromMem(p + 0x28);
+ h.NumParts = GetUInt16FromMem(p + 0x2A);
+ int offset = 0x2C;
+ if (h.IsNewVersion())
+ {
+ h.NumImages = GetUInt32FromMem(p + offset);
+ offset += 4;
+ }
+ GetResource(p + offset, h.OffsetResource);
+ GetResource(p + offset + 0x18, h.XmlResource);
+ GetResource(p + offset + 0x30, h.MetadataResource);
+ /*
+ if (h.IsNewVersion())
+ {
+ if (haderSize < 0xD0)
+ return S_FALSE;
+ GetResource(p + offset + 0x4C, h.IntegrityResource);
+ h.BootIndex = GetUInt32FromMem(p + 0x48);
+ }
+ */
+ return S_OK;
+}
+
+HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
+{
+ CByteBuffer offsetBuf;
+ RINOK(UnpackData(inStream, h.OffsetResource, offsetBuf, NULL));
+ for (size_t i = 0; i + kStreamInfoSize <= offsetBuf.GetCapacity(); i += kStreamInfoSize)
+ {
+ CStreamInfo s;
+ GetStream((const Byte *)offsetBuf + i, s);
+ if (s.PartNumber == h.PartNumber)
+ db.Streams.Add(s);
+ }
+ return S_OK;
+}
+
+HRESULT OpenArchive(IInStream *inStream, const CHeader &h, CByteBuffer &xml, CDatabase &db)
+{
+ RINOK(UnpackData(inStream, h.XmlResource, xml, NULL));
+
+ RINOK(ReadStreams(inStream, h, db));
+ bool needBootMetadata = !h.MetadataResource.IsEmpty();
+ if (h.PartNumber == 1)
+ {
+ int imageIndex = 1;
+ for (int j = 0; j < db.Streams.Size(); j++)
+ {
+ // if (imageIndex > 1) break;
+ const CStreamInfo &si = db.Streams[j];
+ if (!si.Resource.IsMetadata() || si.PartNumber != h.PartNumber)
+ continue;
+ Byte hash[kHashSize];
+ CByteBuffer metadata;
+ RINOK(UnpackData(inStream, si.Resource, metadata, hash));
+ if (memcmp(hash, si.Hash, kHashSize) != 0)
+ return S_FALSE;
+ wchar_t sz[32];
+ ConvertUInt64ToString(imageIndex++, sz);
+ UString s = sz;
+ s += WCHAR_PATH_SEPARATOR;
+ RINOK(ParseDir(metadata, metadata.GetCapacity(), s, db.Items));
+ if (needBootMetadata)
+ if (h.MetadataResource.Offset == si.Resource.Offset)
+ needBootMetadata = false;
+ }
+ }
+
+ if (needBootMetadata)
+ {
+ CByteBuffer metadata;
+ RINOK(UnpackData(inStream, h.MetadataResource, metadata, NULL));
+ RINOK(ParseDir(metadata, metadata.GetCapacity(), L"0" WSTRING_PATH_SEPARATOR, db.Items));
+ }
+ return S_OK;
+}
+
+
+HRESULT SortDatabase(CDatabase &db)
+{
+ db.Streams.Sort(CompareStreamsByPos, NULL);
+
+ {
+ CRecordVector<int> sortedByHash;
+ {
+ for (int j = 0; j < db.Streams.Size(); j++)
+ sortedByHash.Add(j);
+ sortedByHash.Sort(CompareHashRefs, &db.Streams);
+ }
+
+ for (int i = 0; i < db.Items.Size(); i++)
+ {
+ CItem &item = db.Items[i];
+ item.StreamIndex = -1;
+ if (item.HasStream())
+ item.StreamIndex = FindHash(db.Streams, sortedByHash, item.Hash);
+ }
+ }
+
+ {
+ CRecordVector<bool> used;
+ int j;
+ for (j = 0; j < db.Streams.Size(); j++)
+ {
+ const CStreamInfo &s = db.Streams[j];
+ used.Add(s.Resource.IsMetadata() && s.PartNumber == 1);
+ }
+ for (int i = 0; i < db.Items.Size(); i++)
+ {
+ CItem &item = db.Items[i];
+ if (item.StreamIndex >= 0)
+ used[item.StreamIndex] = true;
+ }
+ for (j = 0; j < db.Streams.Size(); j++)
+ if (!used[j])
+ {
+ CItem item;
+ item.StreamIndex = j;
+ item.HasMetadata = false;
+ db.Items.Add(item);
+ }
+ }
+
+ db.Items.Sort(CompareItems, NULL);
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
new file mode 100755
index 00000000..bc74f61b
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -0,0 +1,139 @@
+// 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<CStreamInfo> Streams;
+ CObjectVector<CItem> Items;
+ 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<ICompressCoder> copyCoder;
+
+ NCompress::NLzx::CDecoder *lzxDecoderSpec;
+ CMyComPtr<ICompressCoder> 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
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
new file mode 100755
index 00000000..22344b3a
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -0,0 +1,13 @@
+// WimRegister.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/RegisterArc.h"
+
+#include "WimHandler.h"
+static IInArchive *CreateArc() { return new NArchive::NWim::CHandler; }
+
+static CArcInfo g_ArcInfo =
+ { L"Wim", L"wim swm", 0, 0xE6, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 }, 8, false, CreateArc, 0 };
+
+REGISTER_ARC(Wim)
diff --git a/CPP/7zip/Archive/Wim/wim.ico b/CPP/7zip/Archive/Wim/wim.ico
new file mode 100755
index 00000000..887975e6
--- /dev/null
+++ b/CPP/7zip/Archive/Wim/wim.ico
Binary files differ
diff --git a/CPP/7zip/Bundles/Format7zF/Format7z.dsp b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
index 66ae5d92..0f8407cc 100755
--- a/CPP/7zip/Bundles/Format7zF/Format7z.dsp
+++ b/CPP/7zip/Bundles/Format7zF/Format7z.dsp
@@ -130,6 +130,10 @@ SOURCE=.\StdAfx.h
# PROP Default_Filter ""
# Begin Source File
+SOURCE=..\..\..\Common\Buffer.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\CRC.cpp
# End Source File
# Begin Source File
@@ -142,10 +146,18 @@ SOURCE=..\..\..\Common\IntToString.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\MyCom.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\MyException.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\MyInitGuid.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\MyString.cpp
# End Source File
# Begin Source File
@@ -154,6 +166,10 @@ SOURCE=..\..\..\Common\MyString.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\MyUnknown.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\MyVector.cpp
# End Source File
# Begin Source File
@@ -162,10 +178,18 @@ SOURCE=..\..\..\Common\MyVector.h
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\MyWindows.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\NewHandler.cpp
# End Source File
# Begin Source File
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\..\Common\StringConvert.cpp
# End Source File
# Begin Source File
@@ -1902,6 +1926,14 @@ SOURCE=..\..\Archive\Common\OutStreamWithCRC.h
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\Common\OutStreamWithSha1.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Common\OutStreamWithSha1.h
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Common\ParseProperties.cpp
# End Source File
# Begin Source File
@@ -2349,6 +2381,30 @@ SOURCE=..\..\Archive\Zip\ZipUpdate.cpp
SOURCE=..\..\Archive\Zip\ZipUpdate.h
# End Source File
# End Group
+# Begin Group "Wim"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Archive\Wim\WimHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Wim\WimHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Wim\WimIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Wim\WimIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Archive\Wim\WimRegister.cpp
+# End Source File
+# End Group
# Begin Source File
SOURCE=..\..\Archive\IArchive.h
@@ -2420,6 +2476,10 @@ SOURCE=..\..\Archive\Tar\tar.ico
# End Source File
# Begin Source File
+SOURCE=..\..\Archive\Wim\wim.ico
+# End Source File
+# Begin Source File
+
SOURCE=..\..\Archive\Z\Z.ico
# End Source File
# Begin Source File
diff --git a/CPP/7zip/Bundles/Format7zF/makefile b/CPP/7zip/Bundles/Format7zF/makefile
index d3e9d8c7..0f3bf3d1 100755
--- a/CPP/7zip/Bundles/Format7zF/makefile
+++ b/CPP/7zip/Bundles/Format7zF/makefile
@@ -62,6 +62,7 @@ AR_COMMON_OBJS = \
$O\ItemNameUtils.obj \
$O\MultiStream.obj \
$O\OutStreamWithCRC.obj \
+ $O\OutStreamWithSha1.obj \
$O\HandlerOut.obj \
$O\ParseProperties.obj \
@@ -174,6 +175,11 @@ TAR_OBJS = \
$O\TarUpdate.obj \
$O\TarRegister.obj \
+WIM_OBJS = \
+ $O\WimHandler.obj \
+ $O\WimIn.obj \
+ $O\WimRegister.obj \
+
Z_OBJS = \
$O\ZHandler.obj \
$O\ZRegister.obj \
@@ -345,6 +351,7 @@ OBJS = \
$(RPM_OBJS) \
$(SPLIT_OBJS) \
$(TAR_OBJS) \
+ $(WIM_OBJS) \
$(Z_OBJS) \
$(ZIP_OBJS) \
$(BZIP2_OBJS) \
@@ -426,6 +433,8 @@ $(SPLIT_OBJS): ../../Archive/Split/$(*B).cpp
$(COMPL)
$(TAR_OBJS): ../../Archive/Tar/$(*B).cpp
$(COMPL)
+$(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
+ $(COMPL)
$(Z_OBJS): ../../Archive/Z/$(*B).cpp
$(COMPL)
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
diff --git a/CPP/7zip/Bundles/Format7zF/resource.rc b/CPP/7zip/Bundles/Format7zF/resource.rc
index 9bf56129..365c0637 100755
--- a/CPP/7zip/Bundles/Format7zF/resource.rc
+++ b/CPP/7zip/Bundles/Format7zF/resource.rc
@@ -18,9 +18,10 @@ MY_VERSION_INFO_DLL("7z Standalone Plugin", "7za")
12 ICON "../../Archive/Cpio/cpio.ico"
13 ICON "../../Archive/Tar/tar.ico"
14 ICON "../../Archive/GZip/gz.ico"
+15 ICON "../../Archive/Wim/wim.ico"
STRINGTABLE
BEGIN
- 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14"
+ 100 "7z:0 zip:1 bz2:2 bzip2:2 tbz2:2 tbz:2 rar:3 arj:4 z:5 taz:5 lzh:6 lha:6 cab:7 iso:8 split:9 rpm:10 deb:11 cpio:12 tar:13 gz:14 gzip:14 tgz:14 tpz:14 wim:15 swm:15"
END
diff --git a/CPP/7zip/Common/FilterCoder.cpp b/CPP/7zip/Common/FilterCoder.cpp
index 76d022d2..35c344c3 100755
--- a/CPP/7zip/Common/FilterCoder.cpp
+++ b/CPP/7zip/Common/FilterCoder.cpp
@@ -234,6 +234,12 @@ STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
#endif
#ifndef EXTRACT_ONLY
+STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs,
+ const PROPVARIANT *properties, UInt32 numProperties)
+{
+ return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
+}
+
STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
{
return _writeCoderProperties->WriteCoderProperties(outStream);
diff --git a/CPP/7zip/Common/FilterCoder.h b/CPP/7zip/Common/FilterCoder.h
index 1b9b29de..f654ae3f 100755
--- a/CPP/7zip/Common/FilterCoder.h
+++ b/CPP/7zip/Common/FilterCoder.h
@@ -25,6 +25,7 @@ class CFilterCoder:
public ICryptoSetPassword,
#endif
#ifndef EXTRACT_ONLY
+ public ICompressSetCoderProperties,
public ICompressWriteCoderProperties,
// public ICryptoResetSalt,
public ICryptoResetInitVector,
@@ -54,6 +55,7 @@ protected:
CMyComPtr<ICryptoSetPassword> _setPassword;
#ifndef EXTRACT_ONLY
+ CMyComPtr<ICompressSetCoderProperties> _SetCoderProperties;
CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
// CMyComPtr<ICryptoResetSalt> _CryptoResetSalt;
CMyComPtr<ICryptoResetInitVector> _CryptoResetInitVector;
@@ -85,6 +87,7 @@ public:
#endif
#ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY_AG(ICompressSetCoderProperties, Filter, _SetCoderProperties)
MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
// MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetSalt, Filter, _CryptoResetSalt)
MY_QUERYINTERFACE_ENTRY_AG(ICryptoResetInitVector, Filter, _CryptoResetInitVector)
@@ -110,6 +113,8 @@ public:
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
#endif
#ifndef EXTRACT_ONLY
+ STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
+ const PROPVARIANT *properties, UInt32 numProperties);
STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
// STDMETHOD(ResetSalt)();
STDMETHOD(ResetInitVector)();
diff --git a/CPP/7zip/Common/InMemStream.h b/CPP/7zip/Common/InMemStream.h
index 73f344ee..636718c6 100755
--- a/CPP/7zip/Common/InMemStream.h
+++ b/CPP/7zip/Common/InMemStream.h
@@ -85,7 +85,7 @@ public:
HRes AllocateList(int numItems)
{
if (!CResourceList::AllocateList(numItems))
- return false;
+ return E_OUTOFMEMORY;
Semaphore.Close();
return Semaphore.Create(numItems, numItems);
}
diff --git a/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp b/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
index 90c122fc..d8d785e2 100755
--- a/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
+++ b/CPP/7zip/Compress/LZMA_Alone/LzmaAlone.cpp
@@ -159,7 +159,7 @@ int main2(int n, const char *args[])
g_IsNT = IsItWindowsNT();
#endif
- fprintf(stderr, "\nLZMA 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-24\n");
+ fprintf(stderr, "\nLZMA 4.49 Copyright (c) 1999-2007 Igor Pavlov 2007-07-05\n");
if (n == 1)
{
diff --git a/CPP/7zip/Compress/Lzx/LzxDecoder.cpp b/CPP/7zip/Compress/Lzx/LzxDecoder.cpp
index 0ba4b822..8beb879b 100755
--- a/CPP/7zip/Compress/Lzx/LzxDecoder.cpp
+++ b/CPP/7zip/Compress/Lzx/LzxDecoder.cpp
@@ -16,9 +16,10 @@ namespace NLzx {
const int kLenIdNeedInit = -2;
-CDecoder::CDecoder():
+CDecoder::CDecoder(bool wimMode):
_keepHistory(false),
- m_AlignPos(0)
+ m_AlignPos(0),
+ _wimMode(wimMode)
{
m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;
m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;
@@ -96,12 +97,18 @@ bool CDecoder::ReadTables(void)
int blockType = (int)ReadBits(kNumBlockTypeBits);
if (blockType > kBlockTypeUncompressed)
return false;
- m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
-
+ if (_wimMode)
+ if (ReadBits(1) == 1)
+ m_UnCompressedBlockSize = (1 << 15);
+ else
+ m_UnCompressedBlockSize = ReadBits(16);
+ else
+ m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
+
m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);
if (m_IsUncompressedBlock)
{
- m_InBitStream.ReadBits(16 - m_InBitStream.GetBitPosition());
+ ReadBits(16 - m_InBitStream.GetBitPosition());
if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))
return false;
m_RepDistances[0]--;
@@ -171,12 +178,16 @@ HRESULT CDecoder::CodeSpec(UInt32 curSize)
{
m_UnCompressedBlockSize = 0;
ClearPrevLevels();
- UInt32 i86TranslationSize = 0;
- bool translationMode = (ReadBits(1) != 0);
- if (translationMode)
+ UInt32 i86TranslationSize = 12000000;
+ bool translationMode = true;
+ if (!_wimMode)
{
- i86TranslationSize = ReadBits(16) << 16;
- i86TranslationSize |= ReadBits(16);
+ translationMode = (ReadBits(1) != 0);
+ if (translationMode)
+ {
+ i86TranslationSize = ReadBits(16) << 16;
+ i86TranslationSize |= ReadBits(16);
+ }
}
m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
diff --git a/CPP/7zip/Compress/Lzx/LzxDecoder.h b/CPP/7zip/Compress/Lzx/LzxDecoder.h
index a62662ec..7c549f45 100755
--- a/CPP/7zip/Compress/Lzx/LzxDecoder.h
+++ b/CPP/7zip/Compress/Lzx/LzxDecoder.h
@@ -139,6 +139,8 @@ class CDecoder :
int _remainLen;
int m_AlignPos;
+ bool _wimMode;
+
UInt32 ReadBits(UInt32 numBits);
bool ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols);
bool ReadTables();
@@ -151,7 +153,7 @@ class CDecoder :
const UInt64 *inSize, const UInt64 *outSize,
ICompressProgressInfo *progress);
public:
- CDecoder();
+ CDecoder(bool wimMode = false);
MY_UNKNOWN_IMP
diff --git a/CPP/7zip/Crypto/Hash/RandGen.cpp b/CPP/7zip/Crypto/Hash/RandGen.cpp
index 480e04ca..9ae36155 100755
--- a/CPP/7zip/Crypto/Hash/RandGen.cpp
+++ b/CPP/7zip/Crypto/Hash/RandGen.cpp
@@ -8,11 +8,24 @@
#include "RandGen.h"
+#ifndef _WIN32
+#include <unistd.h>
+#define USE_POSIX_TIME
+#define USE_POSIX_TIME2
+#endif
+
+#ifdef USE_POSIX_TIME
+#include <time.h>
+#ifdef USE_POSIX_TIME2
+#include <sys/time.h>
+#endif
+#endif
+
// This is not very good random number generator.
// Please use it only for salt.
-// First genrated data block depends from timer.
-// Other genrated data blocks depend from previous state
-// Maybe it's possible to restore original timer vaue from generated value.
+// First generated data block depends from timer and processID.
+// Other generated data blocks depend from previous state
+// Maybe it's possible to restore original timer value from generated value.
void CRandomGenerator::Init()
{
@@ -24,6 +37,11 @@ void CRandomGenerator::Init()
hash.Update((const Byte *)&w, sizeof(w));
w = ::GetCurrentThreadId();
hash.Update((const Byte *)&w, sizeof(w));
+ #else
+ pid_t pid = getpid();
+ hash.Update((const Byte *)&pid, sizeof(pid));
+ pid = getppid();
+ hash.Update((const Byte *)&pid, sizeof(pid));
#endif
for (int i = 0; i < 1000; i++)
@@ -34,6 +52,19 @@ void CRandomGenerator::Init()
hash.Update((const Byte *)&v.QuadPart, sizeof(v.QuadPart));
#endif
+ #ifdef USE_POSIX_TIME
+ #ifdef USE_POSIX_TIME2
+ timeval v;
+ if (gettimeofday(&v, 0) == 0)
+ {
+ hash.Update((const Byte *)&v.tv_sec, sizeof(v.tv_sec));
+ hash.Update((const Byte *)&v.tv_usec, sizeof(v.tv_usec));
+ }
+ #endif
+ time_t v2 = time(NULL);
+ hash.Update((const Byte *)&v2, sizeof(v2));
+ #endif
+
DWORD tickCount = ::GetTickCount();
hash.Update((const Byte *)&tickCount, sizeof(tickCount));
diff --git a/CPP/7zip/Guid.txt b/CPP/7zip/Guid.txt
index bead1f83..2a4d8abb 100755
--- a/CPP/7zip/Guid.txt
+++ b/CPP/7zip/Guid.txt
@@ -121,6 +121,7 @@ Handler GUIDs:
09 Nsis
0A Lzma
+E6 Wim
E7 Iso
E8 Bkf
E9 Chm
diff --git a/CPP/7zip/MyVersion.h b/CPP/7zip/MyVersion.h
index 911dfc15..fbfa0d7d 100755
--- a/CPP/7zip/MyVersion.h
+++ b/CPP/7zip/MyVersion.h
@@ -1,8 +1,8 @@
#define MY_VER_MAJOR 4
-#define MY_VER_MINOR 48
+#define MY_VER_MINOR 49
#define MY_VER_BUILD 0
-#define MY_VERSION "4.48 beta"
-#define MY_7ZIP_VERSION "7-Zip 4.48 beta"
-#define MY_DATE "2007-06-26"
+#define MY_VERSION "4.49 beta"
+#define MY_7ZIP_VERSION "7-Zip 4.49 beta"
+#define MY_DATE "2007-07-11"
#define MY_COPYRIGHT "Copyright (c) 1999-2007 Igor Pavlov"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " " MY_DATE
diff --git a/CPP/7zip/UI/Common/ExtractingFilePath.cpp b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
index a0b17282..cfd4ae79 100755
--- a/CPP/7zip/UI/Common/ExtractingFilePath.cpp
+++ b/CPP/7zip/UI/Common/ExtractingFilePath.cpp
@@ -3,6 +3,21 @@
#include "StdAfx.h"
#include "ExtractingFilePath.h"
+static UString ReplaceIncorrectChars(const UString &s)
+{
+ UString res;
+ for (int i = 0; i < s.Length(); i++)
+ {
+ wchar_t c = s[i];
+ #ifdef _WIN32
+ if (c < 0x20 || c == '*' || c == '?' || c == '<' || c == '>' || c == '|' || c == ':' || c == '"')
+ c = '_';
+ #endif
+ res += c;
+ }
+ return res;
+}
+
static void ReplaceDisk(UString &s)
{
int i;
@@ -58,7 +73,7 @@ UString GetCorrectPath(const UString &path)
result.Replace(L"../", L"");
ReplaceDisk(result);
- return result;
+ return ReplaceIncorrectChars(result);
}
void MakeCorrectPath(UStringVector &pathParts)
diff --git a/CPP/7zip/UI/Common/LoadCodecs.cpp b/CPP/7zip/UI/Common/LoadCodecs.cpp
index 63b59045..a6c97aed 100755
--- a/CPP/7zip/UI/Common/LoadCodecs.cpp
+++ b/CPP/7zip/UI/Common/LoadCodecs.cpp
@@ -28,15 +28,21 @@ static const UINT kIconTypesResId = 100;
using namespace NWindows;
using namespace NFile;
+#ifdef _WIN32
extern HINSTANCE g_hInstance;
+#endif
static CSysString GetLibraryFolderPrefix()
{
+ #ifdef _WIN32
TCHAR fullPath[MAX_PATH + 1];
::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
CSysString path = fullPath;
int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
return path.Left(pos + 1);
+ #else
+ return CSysString(); // FIX IT
+ #endif
}
#define kCodecsFolderName TEXT("Codecs")
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp
index 7891d5f3..48b8506a 100755
--- a/CPP/7zip/UI/Console/List.cpp
+++ b/CPP/7zip/UI/Console/List.cpp
@@ -69,6 +69,7 @@ static const char kArchiveAttributeChar = 'A';
static const char *kListing = "Listing archive: ";
static const wchar_t *kFilesMessage = L"files";
+static const wchar_t *kDirsMessage = L"folders";
static void GetAttributesString(DWORD wa, bool directory, char *s)
{
@@ -118,7 +119,7 @@ CFieldInfoInit kStandardFieldTable[] =
{ kpidAttributes, L"Attr", kRight, kCenter, 1, 5 },
{ kpidSize, L"Size", kRight, kRight, 1, 12 },
{ kpidPackedSize, L"Compressed", kRight, kRight, 1, 12 },
- { kpidPath, L"Name", kLeft, kLeft, 2, 12 }
+ { kpidPath, L"Name", kLeft, kLeft, 2, 24 }
};
void PrintSpaces(int numSpaces)
@@ -162,8 +163,8 @@ public:
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
UInt32 index,
bool techMode);
- HRESULT PrintSummaryInfo(UInt64 numFiles, const UInt64 *size,
- const UInt64 *compressedSize);
+ HRESULT PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
+ const UInt64 *size, const UInt64 *compressedSize);
};
void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
@@ -354,7 +355,7 @@ void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
}
-HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
+HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles, UInt64 numDirs,
const UInt64 *size, const UInt64 *compressedSize)
{
for (int i = 0; i < _fields.Size(); i++)
@@ -373,6 +374,11 @@ HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
UString temp = textString;
temp += L" ";
temp += kFilesMessage;
+ temp += L", ";
+ ConvertUInt64ToString(numDirs, textString);
+ temp += textString;
+ temp += L" ";
+ temp += kDirsMessage;
PrintString(fieldInfo.TextAdjustment, 0, temp);
}
else
@@ -403,7 +409,7 @@ HRESULT ListArchives(
if (!techMode)
fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
- UInt64 numFiles2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
+ UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
for (int i = 0; i < archivePaths.Size(); i++)
{
@@ -465,7 +471,7 @@ HRESULT ListArchives(
{
RINOK(fieldPrinter.Init(archive));
}
- UInt64 numFiles = 0, totalPackSize = 0, totalUnPackSize = 0;
+ UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0;
UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
@@ -495,8 +501,11 @@ HRESULT ListArchives(
totalPackSizePointer = &totalPackSize;
g_StdOut << endl;
-
- numFiles++;
+
+ if (isFolder)
+ numDirs++;
+ else
+ numFiles++;
totalPackSize += packSize;
totalUnPackSize += unpackSize;
}
@@ -504,7 +513,7 @@ HRESULT ListArchives(
{
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
- fieldPrinter.PrintSummaryInfo(numFiles, totalUnPackSizePointer, totalPackSizePointer);
+ fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer);
g_StdOut << endl;
}
if (totalPackSizePointer != 0)
@@ -518,13 +527,14 @@ HRESULT ListArchives(
totalUnPackSize2 += totalUnPackSize;
}
numFiles2 += numFiles;
+ numDirs2 += numDirs;
}
if (enableHeaders && !techMode && archivePaths.Size() > 1)
{
g_StdOut << endl;
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
- fieldPrinter.PrintSummaryInfo(numFiles2, totalUnPackSizePointer2, totalPackSizePointer2);
+ fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2);
g_StdOut << endl;
g_StdOut << "Archives: " << archivePaths.Size() << endl;
}
diff --git a/CPP/7zip/UI/Far/ExtractEngine.cpp b/CPP/7zip/UI/Far/ExtractEngine.cpp
index a71d22b8..d9499a04 100755
--- a/CPP/7zip/UI/Far/ExtractEngine.cpp
+++ b/CPP/7zip/UI/Far/ExtractEngine.cpp
@@ -57,7 +57,7 @@ STDMETHODIMP CExtractCallBackImp::SetCompleted(const UINT64 *completeValue)
STDMETHODIMP CExtractCallBackImp::AskOverwrite(
const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
- const wchar_t *newName, const FILETIME *aNewTime, const UINT64 *newSize,
+ const wchar_t *newName, const FILETIME *newTime, const UINT64 *newSize,
INT32 *answer)
{
NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
@@ -67,8 +67,9 @@ STDMETHODIMP CExtractCallBackImp::AskOverwrite(
oldFileInfo.Size = *existSize;
oldFileInfo.Name = GetSystemString(existName, m_CodePage);
-
- newFileInfo.Time = *aNewTime;
+ newFileInfo.TimeIsDefined = (newTime != 0);
+ if (newFileInfo.TimeIsDefined)
+ newFileInfo.Time = *newTime;
newFileInfo.SizeIsDefined = (newSize != NULL);
if (newFileInfo.SizeIsDefined)
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.cpp b/CPP/7zip/UI/Far/OverwriteDialog.cpp
index 4fbcbc9f..9272942f 100755
--- a/CPP/7zip/UI/Far/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/Far/OverwriteDialog.cpp
@@ -42,14 +42,17 @@ void SetFileInfoStrings(const CFileInfo &fileInfo,
fileInfoStrings.Size = "";
}
- FILETIME localFileTime;
- if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
- throw 4190402;
- UString timeString = ConvertFileTimeToString(localFileTime);
-
- fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
- fileInfoStrings.Time += " ";
- fileInfoStrings.Time += GetSystemString(timeString, CP_OEMCP);
+ FILETIME localFileTime;
+ fileInfoStrings.Time.Empty();
+ if (fileInfo.TimeIsDefined)
+ {
+ if (!FileTimeToLocalFileTime(&fileInfo.Time, &localFileTime))
+ throw 4190402;
+ UString timeString = ConvertFileTimeToString(localFileTime);
+ fileInfoStrings.Time = g_StartupInfo.GetMsgString(NMessageID::kOverwriteModifiedOn);
+ fileInfoStrings.Time += " ";
+ fileInfoStrings.Time += GetSystemString(timeString, CP_OEMCP);
+ }
}
NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo)
diff --git a/CPP/7zip/UI/Far/OverwriteDialog.h b/CPP/7zip/UI/Far/OverwriteDialog.h
index 6ff4590a..4715e53f 100755
--- a/CPP/7zip/UI/Far/OverwriteDialog.h
+++ b/CPP/7zip/UI/Far/OverwriteDialog.h
@@ -10,6 +10,7 @@ namespace NOverwriteDialog {
struct CFileInfo
{
bool SizeIsDefined;
+ bool TimeIsDefined;
UINT64 Size;
FILETIME Time;
CSysString Name;
diff --git a/CPP/7zip/UI/Far/PluginWrite.cpp b/CPP/7zip/UI/Far/PluginWrite.cpp
index 79fdbf8f..80f9916a 100755
--- a/CPP/7zip/UI/Far/PluginWrite.cpp
+++ b/CPP/7zip/UI/Far/PluginWrite.cpp
@@ -4,6 +4,7 @@
#include "Plugin.h"
+#include "Common/Wildcard.h"
#include "Common/StringConvert.h"
#include "Windows/FileDir.h"
@@ -318,6 +319,80 @@ NFileOperationReturnCode::EEnum CPlugin::PutFiles(
return NFileOperationReturnCode::kSuccess;
}
+namespace NPathType
+{
+ enum EEnum
+ {
+ kLocal,
+ kUNC
+ };
+ EEnum GetPathType(const UString &path);
+}
+
+struct CParsedPath
+{
+ UString Prefix; // Disk or UNC with slash
+ UStringVector PathParts;
+ void ParsePath(const UString &path);
+ UString MergePath() const;
+};
+
+static const wchar_t kDirDelimiter = WCHAR_PATH_SEPARATOR;
+static const wchar_t kDiskDelimiter = L':';
+
+namespace NPathType
+{
+ EEnum GetPathType(const UString &path)
+ {
+ if (path.Length() <= 2)
+ return kLocal;
+ if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)
+ return kUNC;
+ return kLocal;
+ }
+}
+
+void CParsedPath::ParsePath(const UString &path)
+{
+ int curPos = 0;
+ switch (NPathType::GetPathType(path))
+ {
+ case NPathType::kLocal:
+ {
+ int posDiskDelimiter = path.Find(kDiskDelimiter);
+ if(posDiskDelimiter >= 0)
+ {
+ curPos = posDiskDelimiter + 1;
+ if (path.Length() > curPos)
+ if(path[curPos] == kDirDelimiter)
+ curPos++;
+ }
+ break;
+ }
+ case NPathType::kUNC:
+ {
+ int curPos = path.Find(kDirDelimiter, 2);
+ if(curPos < 0)
+ curPos = path.Length();
+ else
+ curPos++;
+ }
+ }
+ Prefix = path.Left(curPos);
+ SplitPathToParts(path.Mid(curPos), PathParts);
+}
+
+UString CParsedPath::MergePath() const
+{
+ UString result = Prefix;
+ for(int i = 0; i < PathParts.Size(); i++)
+ {
+ if (i != 0)
+ result += kDirDelimiter;
+ result += PathParts[i];
+ }
+ return result;
+}
/*
@@ -375,7 +450,7 @@ HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
UString resultPath;
{
- NName::CParsedPath parsedPath;
+ CParsedPath parsedPath;
parsedPath.ParsePath(fileNames.Front());
if(parsedPath.PathParts.Size() == 0)
return E_FAIL;
diff --git a/CPP/Common/Buffer.h b/CPP/Common/Buffer.h
index 0b8ac804..78a68a6d 100755
--- a/CPP/Common/Buffer.h
+++ b/CPP/Common/Buffer.h
@@ -10,13 +10,13 @@ template <class T> class CBuffer
protected:
size_t _capacity;
T *_items;
+public:
void Free()
{
delete []_items;
_items = 0;
_capacity = 0;
}
-public:
CBuffer(): _capacity(0), _items(0) {};
CBuffer(const CBuffer &buffer): _capacity(0), _items(0) { *this = buffer; }
CBuffer(size_t size): _items(0), _capacity(0) { SetCapacity(size); }
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
index 7d81d966..340d8655 100755
--- a/CPP/Common/IntToString.cpp
+++ b/CPP/Common/IntToString.cpp
@@ -8,7 +8,7 @@ void ConvertUInt64ToString(UInt64 value, char *s, UInt32 base)
{
if (base < 2 || base > 36)
{
- *s = L'\0';
+ *s = '\0';
return;
}
char temp[72];
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp
index 49e957cf..57c357ff 100755
--- a/CPP/Windows/FileName.cpp
+++ b/CPP/Windows/FileName.cpp
@@ -9,13 +9,6 @@ namespace NWindows {
namespace NFile {
namespace NName {
-static const wchar_t kDiskDelimiter = L':';
-
-/*
-static bool IsCharAPrefixDelimiter(wchar_t c)
- { return (c == kDirDelimiter || c == kDiskDelimiter); }
-*/
-
void NormalizeDirPathPrefix(CSysString &dirPath)
{
if (dirPath.IsEmpty())
@@ -34,59 +27,7 @@ void NormalizeDirPathPrefix(UString &dirPath)
}
#endif
-namespace NPathType
-{
- EEnum GetPathType(const UString &path)
- {
- if (path.Length() <= 2)
- return kLocal;
- if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)
- return kUNC;
- return kLocal;
- }
-}
-
-void CParsedPath::ParsePath(const UString &path)
-{
- int curPos = 0;
- switch (NPathType::GetPathType(path))
- {
- case NPathType::kLocal:
- {
- int posDiskDelimiter = path.Find(kDiskDelimiter);
- if(posDiskDelimiter >= 0)
- {
- curPos = posDiskDelimiter + 1;
- if (path.Length() > curPos)
- if(path[curPos] == kDirDelimiter)
- curPos++;
- }
- break;
- }
- case NPathType::kUNC:
- {
- int curPos = path.Find(kDirDelimiter, 2);
- if(curPos < 0)
- curPos = path.Length();
- else
- curPos++;
- }
- }
- Prefix = path.Left(curPos);
- SplitPathToParts(path.Mid(curPos), PathParts);
-}
-
-UString CParsedPath::MergePath() const
-{
- UString result = Prefix;
- for(int i = 0; i < PathParts.Size(); i++)
- {
- if (i != 0)
- result += kDirDelimiter;
- result += PathParts[i];
- }
- return result;
-}
+#ifdef _WIN32
const wchar_t kExtensionDelimiter = L'.';
@@ -108,4 +49,6 @@ void SplitNameToPureNameAndExtension(const UString &fullName,
}
}
+#endif
+
}}}
diff --git a/CPP/Windows/FileName.h b/CPP/Windows/FileName.h
index 5b912b2d..2eab2679 100755
--- a/CPP/Windows/FileName.h
+++ b/CPP/Windows/FileName.h
@@ -17,26 +17,10 @@ void NormalizeDirPathPrefix(CSysString &dirPath); // ensures that it ended with
void NormalizeDirPathPrefix(UString &dirPath); // ensures that it ended with '\\'
#endif
-namespace NPathType
-{
- enum EEnum
- {
- kLocal,
- kUNC
- };
- EEnum GetPathType(const UString &path);
-}
-
-struct CParsedPath
-{
- UString Prefix; // Disk or UNC with slash
- UStringVector PathParts;
- void ParsePath(const UString &path);
- UString MergePath() const;
-};
-
+#ifdef _WIN32
void SplitNameToPureNameAndExtension(const UString &fullName,
UString &pureName, UString &extensionDelimiter, UString &extension);
+#endif
}}}