This commit is contained in:
Igor Pavlov
2017-04-30 00:00:00 +00:00
committed by Kornel
parent 603abd5528
commit 2efa10565a
442 changed files with 15479 additions and 8525 deletions

View File

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