📄 7zhandler.cpp
字号:
// 7zHandler.cpp
#include "StdAfx.h"
#include "7zHandler.h"
#include "7zProperties.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/ComTry.h"
#include "../../../Windows/Defs.h"
#include "../Common/ItemNameUtils.h"
#ifdef _7Z_VOL
#include "../Common/MultiStream.h"
#endif
#ifdef __7Z_SET_PROPERTIES
#ifdef EXTRACT_ONLY
#include "../Common/ParseProperties.h"
#endif
#endif
#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif
using namespace NWindows;
extern UString ConvertMethodIdToString(UInt64 id);
namespace NArchive {
namespace N7z {
CHandler::CHandler()
{
_crcSize = 4;
#ifdef EXTRACT_ONLY
#ifdef COMPRESS_MT
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
#endif
#else
Init();
#endif
}
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
{
*numItems =
#ifdef _7Z_VOL
_refs.Size();
#else
*numItems = _database.Files.Size();
#endif
return S_OK;
}
#ifdef _SFX
IMP_IInArchive_ArcProps_NO
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
{
return E_NOTIMPL;
}
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
{
return E_NOTIMPL;
}
#else
STATPROPSTG kArcProps[] =
{
{ NULL, kpidMethod, VT_BSTR},
{ NULL, kpidSolid, VT_BOOL},
{ NULL, kpidNumBlocks, VT_UI4}
};
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
switch(propID)
{
case kpidMethod:
{
UString resString;
CRecordVector<UInt64> ids;
int i;
for (i = 0; i < _database.Folders.Size(); i++)
{
const CFolder &f = _database.Folders[i];
for (int j = f.Coders.Size() - 1; j >= 0; j--)
ids.AddToUniqueSorted(f.Coders[j].MethodID);
}
for (i = 0; i < ids.Size(); i++)
{
UInt64 id = ids[i];
UString methodName;
/* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
if (methodName.IsEmpty())
methodName = ConvertMethodIdToString(id);
if (!resString.IsEmpty())
resString += L' ';
resString += methodName;
}
prop = resString;
break;
}
case kpidSolid: prop = _database.IsSolid(); break;
case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
IMP_IInArchive_ArcProps
#endif
static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
{
if (timeDefined)
prop = unixTime;
}
#ifndef _SFX
static UString ConvertUInt32ToString(UInt32 value)
{
wchar_t buffer[32];
ConvertUInt64ToString(value, buffer);
return buffer;
}
static UString GetStringForSizeValue(UInt32 value)
{
for (int i = 31; i >= 0; i--)
if ((UInt32(1) << i) == value)
return ConvertUInt32ToString(i);
UString result;
if (value % (1 << 20) == 0)
{
result += ConvertUInt32ToString(value >> 20);
result += L"m";
}
else if (value % (1 << 10) == 0)
{
result += ConvertUInt32ToString(value >> 10);
result += L"k";
}
else
{
result += ConvertUInt32ToString(value);
result += L"b";
}
return result;
}
static const UInt64 k_Copy = 0x0;
static const UInt64 k_LZMA = 0x030101;
static const UInt64 k_PPMD = 0x030401;
static wchar_t GetHex(Byte value)
{
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
}
static inline UString GetHex2(Byte value)
{
UString result;
result += GetHex((Byte)(value >> 4));
result += GetHex((Byte)(value & 0xF));
return result;
}
#endif
static const UInt64 k_AES = 0x06F10701;
#ifndef _SFX
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
{
return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
}
#endif
bool CHandler::IsEncrypted(UInt32 index2) const
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
if (folderInfo.Coders[i].MethodID == k_AES)
return true;
}
return false;
}
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
/*
const CRef2 &ref2 = _refs[index];
if (ref2.Refs.IsEmpty())
return E_FAIL;
const CRef &ref = ref2.Refs.Front();
*/
#ifdef _7Z_VOL
const CRef &ref = _refs[index];
const CVolume &volume = _volumes[ref.VolumeIndex];
const CArchiveDatabaseEx &_database = volume.Database;
UInt32 index2 = ref.ItemIndex;
const CFileItem &item = _database.Files[index2];
#else
const CFileItem &item = _database.Files[index];
UInt32 index2 = index;
#endif
switch(propID)
{
case kpidPath:
{
if (!item.Name.IsEmpty())
prop = NItemName::GetOSName(item.Name);
break;
}
case kpidIsFolder:
prop = item.IsDirectory;
break;
case kpidSize:
{
prop = item.UnPackSize;
// prop = ref2.UnPackSize;
break;
}
case kpidPosition:
{
/*
if (ref2.Refs.Size() > 1)
prop = ref2.StartPos;
else
*/
if (item.IsStartPosDefined)
prop = item.StartPos;
break;
}
case kpidPackedSize:
{
// prop = ref2.PackSize;
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
prop = _database.GetFolderFullPackSize(folderIndex);
/*
else
prop = (UInt64)0;
*/
}
else
prop = (UInt64)0;
}
break;
}
case kpidLastAccessTime:
MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
break;
case kpidCreationTime:
MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
break;
case kpidLastWriteTime:
MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
break;
case kpidAttributes:
if (item.AreAttributesDefined)
prop = item.Attributes;
break;
case kpidCRC:
if (item.IsFileCRCDefined)
prop = item.FileCRC;
break;
case kpidEncrypted:
{
prop = IsEncrypted(index2);
break;
}
#ifndef _SFX
case kpidMethod:
{
CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
if (folderIndex != kNumNoIndex)
{
const CFolder &folderInfo = _database.Folders[folderIndex];
UString methodsString;
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
if (!methodsString.IsEmpty())
methodsString += L' ';
{
UString methodName;
bool methodIsKnown = FindMethod(
EXTERNAL_CODECS_VARS
coderInfo.MethodID, methodName);
if (methodIsKnown)
{
methodsString += methodName;
if (coderInfo.MethodID == k_LZMA)
{
if (coderInfo.Properties.GetCapacity() >= 5)
{
methodsString += L":";
UInt32 dicSize = GetUInt32FromMemLE(
((const Byte *)coderInfo.Properties + 1));
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (coderInfo.MethodID == k_PPMD)
{
if (coderInfo.Properties.GetCapacity() >= 5)
{
Byte order = *(const Byte *)coderInfo.Properties;
methodsString += L":o";
methodsString += ConvertUInt32ToString(order);
methodsString += L":mem";
UInt32 dicSize = GetUInt32FromMemLE(
((const Byte *)coderInfo.Properties + 1));
methodsString += GetStringForSizeValue(dicSize);
}
}
else if (coderInfo.MethodID == k_AES)
{
if (coderInfo.Properties.GetCapacity() >= 1)
{
methodsString += L":";
const Byte *data = (const Byte *)coderInfo.Properties;
Byte firstByte = *data++;
UInt32 numCyclesPower = firstByte & 0x3F;
methodsString += ConvertUInt32ToString(numCyclesPower);
/*
if ((firstByte & 0xC0) != 0)
{
methodsString += L":";
return S_OK;
UInt32 saltSize = (firstByte >> 7) & 1;
UInt32 ivSize = (firstByte >> 6) & 1;
if (coderInfo.Properties.GetCapacity() >= 2)
{
Byte secondByte = *data++;
saltSize += (secondByte >> 4);
ivSize += (secondByte & 0x0F);
}
}
*/
}
}
else
{
if (coderInfo.Properties.GetCapacity() > 0)
{
methodsString += L":[";
for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
{
if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
{
methodsString += L"..";
break;
}
else
methodsString += GetHex2(coderInfo.Properties[bi]);
}
methodsString += L"]";
}
}
}
else
{
methodsString += ConvertMethodIdToString(coderInfo.MethodID);
}
}
}
prop = methodsString;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -