diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-07-11 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:52 +0300 |
commit | 7038848692e7049234f223703522681a19db49a5 (patch) | |
tree | 38c5acef39a775a1f58f81b13be81fc6ef8c72e3 /CPP | |
parent | fd8b1d78b496fe38193bf8c5e86af3b43f0b022d (diff) |
4.49 beta
Diffstat (limited to 'CPP')
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(¤tTotalSize)); + 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, ¤tTotalSize, ¤tTotalSize); + 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 Binary files differnew file mode 100755 index 00000000..887975e6 --- /dev/null +++ b/CPP/7zip/Archive/Wim/wim.ico 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 }}} |