mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-07 11:14:58 -06:00
17.00
This commit is contained in:
@@ -11,12 +11,14 @@
|
||||
#include "../../Common/MyBuffer.h"
|
||||
|
||||
#include "../../Windows/PropVariant.h"
|
||||
#include "../../Windows/PropVariantUtils.h"
|
||||
|
||||
#include "../Common/RegisterArc.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "HandlerCont.h"
|
||||
|
||||
#define Get16(p) GetUi16(p)
|
||||
#define Get32(p) GetUi32(p)
|
||||
#define Get64(p) GetUi64(p)
|
||||
|
||||
@@ -33,6 +35,7 @@ static const unsigned k_ClusterBits = 20;
|
||||
static const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits;
|
||||
static const UInt32 k_UnusedCluster = 0xFFFFFFFF;
|
||||
|
||||
|
||||
// static const UInt32 kDiskType_Dynamic = 1;
|
||||
// static const UInt32 kDiskType_Static = 2;
|
||||
|
||||
@@ -41,8 +44,38 @@ static const char * const kDiskTypes[] =
|
||||
"0"
|
||||
, "Dynamic"
|
||||
, "Static"
|
||||
, "Undo"
|
||||
, "Diff"
|
||||
};
|
||||
|
||||
|
||||
enum EGuidType
|
||||
{
|
||||
k_GuidType_Creat,
|
||||
k_GuidType_Modif,
|
||||
k_GuidType_Link,
|
||||
k_GuidType_PModif
|
||||
};
|
||||
|
||||
static const unsigned kNumGuids = 4;
|
||||
static const char * const kGuidNames[kNumGuids] =
|
||||
{
|
||||
"Creat "
|
||||
, "Modif "
|
||||
, "Link "
|
||||
, "PModif"
|
||||
};
|
||||
|
||||
static bool IsEmptyGuid(const Byte *data)
|
||||
{
|
||||
for (unsigned i = 0; i < 16; i++)
|
||||
if (data[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CHandler: public CHandlerImg
|
||||
{
|
||||
UInt32 _dataOffset;
|
||||
@@ -52,6 +85,8 @@ class CHandler: public CHandlerImg
|
||||
bool _isArc;
|
||||
bool _unsupported;
|
||||
|
||||
Byte Guids[kNumGuids][16];
|
||||
|
||||
HRESULT Seek(UInt64 offset)
|
||||
{
|
||||
_posInArc = offset;
|
||||
@@ -137,7 +172,9 @@ static const Byte kProps[] =
|
||||
static const Byte kArcProps[] =
|
||||
{
|
||||
kpidHeadersSize,
|
||||
kpidMethod
|
||||
kpidMethod,
|
||||
kpidComment,
|
||||
kpidName
|
||||
};
|
||||
|
||||
IMP_IInArchive_Props
|
||||
@@ -156,16 +193,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
|
||||
case kpidMethod:
|
||||
{
|
||||
char s[16];
|
||||
const char *ptr;
|
||||
if (_imageType < ARRAY_SIZE(kDiskTypes))
|
||||
ptr = kDiskTypes[_imageType];
|
||||
else
|
||||
{
|
||||
ConvertUInt32ToString(_imageType, s);
|
||||
ptr = s;
|
||||
}
|
||||
prop = ptr;
|
||||
TYPE_TO_PROP(kDiskTypes, _imageType, prop);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -181,6 +209,42 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||
prop = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidComment:
|
||||
{
|
||||
AString s;
|
||||
for (unsigned i = 0; i < kNumGuids; i++)
|
||||
{
|
||||
const Byte *guid = Guids[i];
|
||||
if (!IsEmptyGuid(guid))
|
||||
{
|
||||
s.Add_LF();
|
||||
s += kGuidNames[i];
|
||||
s += " : ";
|
||||
char temp[64];
|
||||
RawLeGuidToString_Braced(guid, temp);
|
||||
MyStringLower_Ascii(temp);
|
||||
s += temp;
|
||||
}
|
||||
}
|
||||
if (!s.IsEmpty())
|
||||
prop = s;
|
||||
break;
|
||||
}
|
||||
|
||||
case kpidName:
|
||||
{
|
||||
const Byte *guid = Guids[k_GuidType_Creat];
|
||||
if (!IsEmptyGuid(guid))
|
||||
{
|
||||
char temp[64];
|
||||
RawLeGuidToString_Braced(guid, temp);
|
||||
MyStringLower_Ascii(temp);
|
||||
strcat(temp, ".vdi");
|
||||
prop = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prop.Detach(value);
|
||||
@@ -207,15 +271,6 @@ STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
|
||||
}
|
||||
|
||||
|
||||
static bool IsEmptyGuid(const Byte *data)
|
||||
{
|
||||
for (unsigned i = 0; i < 16; i++)
|
||||
if (data[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallback */)
|
||||
{
|
||||
const unsigned kHeaderSize = 512;
|
||||
@@ -225,45 +280,65 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
|
||||
if (memcmp(buf + 0x40, k_Signature, sizeof(k_Signature)) != 0)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 version = Get32(buf + 0x44);
|
||||
const UInt32 version = Get32(buf + 0x44);
|
||||
if (version >= 0x20000)
|
||||
return S_FALSE;
|
||||
if (version < 0x10000)
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 headerSize = Get32(buf + 0x48);
|
||||
if (headerSize < 0x140 || headerSize > 0x1B8)
|
||||
const unsigned kHeaderOffset = 0x48;
|
||||
const unsigned kGuidsOffsets = 0x188;
|
||||
const UInt32 headerSize = Get32(buf + kHeaderOffset);
|
||||
if (headerSize < kGuidsOffsets - kHeaderOffset || headerSize > 0x200 - kHeaderOffset)
|
||||
return S_FALSE;
|
||||
|
||||
_imageType = Get32(buf + 0x4C);
|
||||
_dataOffset = Get32(buf + 0x158);
|
||||
// Int32 flags = Get32(buf + 0x50);
|
||||
// Byte Comment[0x100]
|
||||
|
||||
UInt32 tableOffset = Get32(buf + 0x154);
|
||||
const UInt32 tableOffset = Get32(buf + 0x154);
|
||||
if (tableOffset < 0x200)
|
||||
return S_FALSE;
|
||||
|
||||
_dataOffset = Get32(buf + 0x158);
|
||||
|
||||
// UInt32 geometry[3];
|
||||
|
||||
UInt32 sectorSize = Get32(buf + 0x168);
|
||||
const UInt32 sectorSize = Get32(buf + 0x168);
|
||||
if (sectorSize != 0x200)
|
||||
return S_FALSE;
|
||||
|
||||
_size = Get64(buf + 0x170);
|
||||
const UInt32 blockSize = Get32(buf + 0x178);
|
||||
const UInt32 totalBlocks = Get32(buf + 0x180);
|
||||
const UInt32 numAllocatedBlocks = Get32(buf + 0x184);
|
||||
|
||||
_isArc = true;
|
||||
|
||||
if (_imageType > 2)
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (_dataOffset < tableOffset)
|
||||
return S_FALSE;
|
||||
|
||||
UInt32 blockSize = Get32(buf + 0x178);
|
||||
if (blockSize != ((UInt32)1 << k_ClusterBits))
|
||||
if (_imageType > 4)
|
||||
_unsupported = true;
|
||||
|
||||
if (blockSize != k_ClusterSize)
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
UInt32 totalBlocks = Get32(buf + 0x180);
|
||||
if (headerSize >= kGuidsOffsets + kNumGuids * 16 - kHeaderOffset)
|
||||
{
|
||||
for (unsigned i = 0; i < kNumGuids; i++)
|
||||
memcpy(Guids[i], buf + kGuidsOffsets + 16 * i, 16);
|
||||
|
||||
if (!IsEmptyGuid(Guids[k_GuidType_Link]) ||
|
||||
!IsEmptyGuid(Guids[k_GuidType_PModif]))
|
||||
_unsupported = true;
|
||||
}
|
||||
|
||||
{
|
||||
UInt64 size2 = (UInt64)totalBlocks << k_ClusterBits;
|
||||
@@ -278,18 +353,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
|
||||
*/
|
||||
}
|
||||
|
||||
if (headerSize >= 0x180)
|
||||
{
|
||||
if (!IsEmptyGuid(buf + 0x1A8) ||
|
||||
!IsEmptyGuid(buf + 0x1B8))
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 numAllocatedBlocks = Get32(buf + 0x184);
|
||||
|
||||
{
|
||||
UInt32 tableReserved = _dataOffset - tableOffset;
|
||||
if ((tableReserved >> 2) < totalBlocks)
|
||||
@@ -298,11 +361,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
|
||||
|
||||
_phySize = _dataOffset + ((UInt64)numAllocatedBlocks << k_ClusterBits);
|
||||
|
||||
size_t numBytes = (size_t)totalBlocks * 4;
|
||||
const size_t numBytes = (size_t)totalBlocks * 4;
|
||||
if ((numBytes >> 2) != totalBlocks)
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_table.Alloc(numBytes);
|
||||
@@ -316,7 +379,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallbac
|
||||
if (v == k_UnusedCluster)
|
||||
continue;
|
||||
if (v >= numAllocatedBlocks)
|
||||
{
|
||||
_unsupported = true;
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Stream = stream;
|
||||
@@ -332,6 +398,9 @@ STDMETHODIMP CHandler::Close()
|
||||
_isArc = false;
|
||||
_unsupported = false;
|
||||
|
||||
for (unsigned i = 0; i < kNumGuids; i++)
|
||||
memset(Guids[i], 0, 16);
|
||||
|
||||
_imgExt = NULL;
|
||||
Stream.Release();
|
||||
return S_OK;
|
||||
|
||||
Reference in New Issue
Block a user