mirror of
https://github.com/ip7z/7zip.git
synced 2025-12-06 07:12:00 +01:00
24.08
This commit is contained in:
parent
a7a1d4a241
commit
e008ce3976
|
|
@ -1,7 +1,7 @@
|
||||||
#define MY_VER_MAJOR 24
|
#define MY_VER_MAJOR 24
|
||||||
#define MY_VER_MINOR 07
|
#define MY_VER_MINOR 8
|
||||||
#define MY_VER_BUILD 0
|
#define MY_VER_BUILD 0
|
||||||
#define MY_VERSION_NUMBERS "24.07"
|
#define MY_VERSION_NUMBERS "24.08"
|
||||||
#define MY_VERSION MY_VERSION_NUMBERS
|
#define MY_VERSION MY_VERSION_NUMBERS
|
||||||
|
|
||||||
#ifdef MY_CPU_NAME
|
#ifdef MY_CPU_NAME
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#define MY_VERSION_CPU MY_VERSION
|
#define MY_VERSION_CPU MY_VERSION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MY_DATE "2024-06-19"
|
#define MY_DATE "2024-08-11"
|
||||||
#undef MY_COPYRIGHT
|
#undef MY_COPYRIGHT
|
||||||
#undef MY_VERSION_COPYRIGHT_DATE
|
#undef MY_VERSION_COPYRIGHT_DATE
|
||||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/* CpuArch.c -- CPU specific code
|
/* CpuArch.c -- CPU specific code
|
||||||
2024-05-18 : Igor Pavlov : Public domain */
|
2024-07-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Precomp.h"
|
#include "Precomp.h"
|
||||||
|
|
||||||
|
|
@ -848,7 +848,11 @@ static unsigned long MY_getauxval(int aux)
|
||||||
|
|
||||||
#define MY_HWCAP_CHECK_FUNC(name) \
|
#define MY_HWCAP_CHECK_FUNC(name) \
|
||||||
BoolInt CPU_IsSupported_ ## name(void) { return 0; }
|
BoolInt CPU_IsSupported_ ## name(void) { return 0; }
|
||||||
|
#if defined(__ARM_NEON)
|
||||||
|
BoolInt CPU_IsSupported_NEON(void) { return True; }
|
||||||
|
#else
|
||||||
MY_HWCAP_CHECK_FUNC(NEON)
|
MY_HWCAP_CHECK_FUNC(NEON)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // USE_HWCAP
|
#endif // USE_HWCAP
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,7 @@ static const char * const g_Machines[] =
|
||||||
static const CUInt32PCharPair g_MachinePairs[] =
|
static const CUInt32PCharPair g_MachinePairs[] =
|
||||||
{
|
{
|
||||||
{ 243, "RISC-V" },
|
{ 243, "RISC-V" },
|
||||||
|
{ 258, "LoongArch" },
|
||||||
{ 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
|
{ 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
|
||||||
{ 0xbaab, "Xilinx MicroBlaze" }
|
{ 0xbaab, "Xilinx MicroBlaze" }
|
||||||
};
|
};
|
||||||
|
|
@ -853,10 +854,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
else if (_header.Machine == k_Machine_MIPS)
|
else if (_header.Machine == k_Machine_MIPS)
|
||||||
{
|
{
|
||||||
const UInt32 ver = flags >> 28;
|
const UInt32 ver = flags >> 28;
|
||||||
s += "v";
|
s.Add_Char('v');
|
||||||
s.Add_UInt32(ver);
|
s.Add_UInt32(ver);
|
||||||
flags &= ((UInt32)1 << 28) - 1;
|
flags &= ((UInt32)1 << 28) - 1;
|
||||||
|
|
||||||
const UInt32 abi = (flags >> 12) & 7;
|
const UInt32 abi = (flags >> 12) & 7;
|
||||||
if (abi)
|
if (abi)
|
||||||
{
|
{
|
||||||
|
|
@ -864,7 +864,6 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
s.Add_UInt32(abi);
|
s.Add_UInt32(abi);
|
||||||
}
|
}
|
||||||
flags &= ~((UInt32)7 << 12);
|
flags &= ~((UInt32)7 << 12);
|
||||||
|
|
||||||
s.Add_Space();
|
s.Add_Space();
|
||||||
s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);
|
s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);
|
||||||
}
|
}
|
||||||
|
|
@ -885,6 +884,31 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
flags &= ~(UInt32)6;
|
flags &= ~(UInt32)6;
|
||||||
s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);
|
s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
#define k_Machine_LOONGARCH 258
|
||||||
|
else if (_header.Machine == k_Machine_LOONGARCH)
|
||||||
|
{
|
||||||
|
s += "ABI:";
|
||||||
|
s.Add_UInt32((flags >> 6) & 3);
|
||||||
|
s.Add_Dot();
|
||||||
|
s.Add_UInt32((flags >> 3) & 7);
|
||||||
|
s.Add_Dot();
|
||||||
|
#if 1
|
||||||
|
s.Add_UInt32(flags & 7);
|
||||||
|
#else
|
||||||
|
static const char k_LoongArch_Float_Type[8] = { '0', 's', 'f', 'd', '4' ,'5', '6', '7' };
|
||||||
|
s.Add_Char(k_LoongArch_Float_Type[flags & 7]);
|
||||||
|
#endif
|
||||||
|
flags &= ~(UInt32)0xff;
|
||||||
|
if (flags)
|
||||||
|
{
|
||||||
|
s.Add_Colon();
|
||||||
|
char sz[16];
|
||||||
|
ConvertUInt32ToHex(flags, sz);
|
||||||
|
s += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char sz[16];
|
char sz[16];
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,12 @@ static const CPartType kPartTypes[] =
|
||||||
|
|
||||||
{ 0x0FC63DAF, NULL, "Linux Data" },
|
{ 0x0FC63DAF, NULL, "Linux Data" },
|
||||||
{ 0x0657FD6D, NULL, "Linux Swap" },
|
{ 0x0657FD6D, NULL, "Linux Swap" },
|
||||||
|
{ 0x44479540, NULL, "Linux root (x86)" },
|
||||||
|
{ 0x4F68BCE3, NULL, "Linux root (x86-64)" },
|
||||||
|
{ 0x69DAD710, NULL, "Linux root (ARM)" },
|
||||||
|
{ 0xB921B045, NULL, "Linux root (ARM64)" },
|
||||||
|
{ 0x993D8D3D, NULL, "Linux root (IA-64)" },
|
||||||
|
|
||||||
|
|
||||||
{ 0x83BD6B9D, NULL, "FreeBSD Boot" },
|
{ 0x83BD6B9D, NULL, "FreeBSD Boot" },
|
||||||
{ 0x516E7CB4, NULL, "FreeBSD Data" },
|
{ 0x516E7CB4, NULL, "FreeBSD Data" },
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,32 @@ struct CDirLink
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IMAGE_DIRECTORY_ENTRY_*
|
||||||
|
static const char * const g_Dir_Names[] =
|
||||||
|
{
|
||||||
|
"EXPORT"
|
||||||
|
, "IMPORT"
|
||||||
|
, "RESOURCE"
|
||||||
|
, "EXCEPTION"
|
||||||
|
, "SECURITY"
|
||||||
|
, "BASERELOC"
|
||||||
|
, "DEBUG"
|
||||||
|
, "ARCHITECTURE" // "COPYRIGHT"
|
||||||
|
, "GLOBALPTR"
|
||||||
|
, "TLS"
|
||||||
|
, "LOAD_CONFIG"
|
||||||
|
, "BOUND_IMPORT"
|
||||||
|
, "IAT"
|
||||||
|
, "DELAY_IMPORT"
|
||||||
|
, "COM_DESCRIPTOR"
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
kDirLink_EXCEPTION = 3,
|
||||||
kDirLink_Certificate = 4,
|
kDirLink_Certificate = 4,
|
||||||
|
kDirLink_BASERELOC = 5,
|
||||||
kDirLink_Debug = 6
|
kDirLink_Debug = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -229,7 +252,7 @@ struct COptHeader
|
||||||
UInt32 UninitDataSize;
|
UInt32 UninitDataSize;
|
||||||
|
|
||||||
// UInt32 AddressOfEntryPoint;
|
// UInt32 AddressOfEntryPoint;
|
||||||
// UInt32 BaseOfCode;
|
// UInt32 BaseOfCode; // VA(.text) == 0x1000 in most cases
|
||||||
// UInt32 BaseOfData32;
|
// UInt32 BaseOfData32;
|
||||||
UInt64 ImageBase;
|
UInt64 ImageBase;
|
||||||
|
|
||||||
|
|
@ -273,6 +296,7 @@ struct COptHeader
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// size is 16-bit
|
||||||
bool COptHeader::Parse(const Byte *p, UInt32 size)
|
bool COptHeader::Parse(const Byte *p, UInt32 size)
|
||||||
{
|
{
|
||||||
if (size < k_OptHeader32_Size_MIN)
|
if (size < k_OptHeader32_Size_MIN)
|
||||||
|
|
@ -334,14 +358,18 @@ bool COptHeader::Parse(const Byte *p, UInt32 size)
|
||||||
pos = 92;
|
pos = 92;
|
||||||
}
|
}
|
||||||
|
|
||||||
G32(pos, NumDirItems);
|
UInt32 numDirItems;
|
||||||
if (NumDirItems > (1 << 16))
|
G32(pos, numDirItems);
|
||||||
|
NumDirItems = numDirItems;
|
||||||
|
if (numDirItems > (1 << 13))
|
||||||
return false;
|
return false;
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if (pos + 8 * NumDirItems > size)
|
if (pos + 8 * numDirItems > size)
|
||||||
return false;
|
return false;
|
||||||
memset((void *)DirItems, 0, sizeof(DirItems));
|
memset((void *)DirItems, 0, sizeof(DirItems));
|
||||||
for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++)
|
if (numDirItems > kNumDirItemsMax)
|
||||||
|
numDirItems = kNumDirItemsMax;
|
||||||
|
for (UInt32 i = 0; i < numDirItems; i++)
|
||||||
DirItems[i].Parse(p + pos + i * 8);
|
DirItems[i].Parse(p + pos + i * 8);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -352,27 +380,41 @@ struct CSection
|
||||||
{
|
{
|
||||||
AString Name;
|
AString Name;
|
||||||
|
|
||||||
|
UInt32 ExtractSize;
|
||||||
UInt32 VSize;
|
UInt32 VSize;
|
||||||
UInt32 Va;
|
UInt32 Va;
|
||||||
UInt32 PSize;
|
UInt32 PSize;
|
||||||
UInt32 Pa;
|
UInt32 Pa;
|
||||||
UInt32 Flags;
|
UInt32 Flags;
|
||||||
UInt32 Time;
|
UInt32 Time;
|
||||||
// UInt16 NumRelocs;
|
// UInt16 NumRelocs; // is set to zero for executable images
|
||||||
bool IsRealSect;
|
bool IsRealSect;
|
||||||
bool IsDebug;
|
bool IsDebug;
|
||||||
bool IsAdditionalSection;
|
bool IsAdditionalSection;
|
||||||
|
|
||||||
CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {}
|
CSection():
|
||||||
|
ExtractSize(0),
|
||||||
|
IsRealSect(false),
|
||||||
|
IsDebug(false),
|
||||||
|
IsAdditionalSection(false)
|
||||||
|
// , NumRelocs(0)
|
||||||
|
{}
|
||||||
|
|
||||||
UInt32 GetSizeExtract() const { return PSize; }
|
void Set_Size_for_all(UInt32 size)
|
||||||
UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
|
{
|
||||||
|
PSize = VSize = ExtractSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 GetSize_Extract() const
|
||||||
|
{
|
||||||
|
return ExtractSize;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateTotalSize(UInt32 &totalSize) const
|
void UpdateTotalSize(UInt32 &totalSize) const
|
||||||
{
|
{
|
||||||
UInt32 t = Pa + PSize;
|
const UInt32 t = Pa + PSize;
|
||||||
if (totalSize < t)
|
if (totalSize < t)
|
||||||
totalSize = t;
|
totalSize = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parse(const Byte *p);
|
void Parse(const Byte *p);
|
||||||
|
|
@ -380,8 +422,8 @@ struct CSection
|
||||||
int Compare(const CSection &s) const
|
int Compare(const CSection &s) const
|
||||||
{
|
{
|
||||||
RINOZ(MyCompare(Pa, s.Pa))
|
RINOZ(MyCompare(Pa, s.Pa))
|
||||||
UInt32 size1 = GetSizeExtract();
|
const UInt32 size1 = GetSize_Extract();
|
||||||
UInt32 size2 = s.GetSizeExtract();
|
const UInt32 size2 = s.GetSize_Extract();
|
||||||
return MyCompare(size1, size2);
|
return MyCompare(size1, size2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -402,6 +444,10 @@ void CSection::Parse(const Byte *p)
|
||||||
G32(20, Pa);
|
G32(20, Pa);
|
||||||
// G16(32, NumRelocs);
|
// G16(32, NumRelocs);
|
||||||
G32(36, Flags);
|
G32(36, Flags);
|
||||||
|
// v24.08: we extract only useful data (without extra padding bytes).
|
||||||
|
// VSize == 0 is not expected, but we support that case too.
|
||||||
|
// return (VSize && VSize < PSize) ? VSize : PSize;
|
||||||
|
ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -508,6 +554,7 @@ static const CUInt32PCharPair g_MachinePairs[] =
|
||||||
{ 0x01D3, "AM33" },
|
{ 0x01D3, "AM33" },
|
||||||
{ 0x01F0, "PPC" },
|
{ 0x01F0, "PPC" },
|
||||||
{ 0x01F1, "PPC-FP" },
|
{ 0x01F1, "PPC-FP" },
|
||||||
|
{ 0x01F2, "PPC-BE" },
|
||||||
{ 0x0200, "IA-64" },
|
{ 0x0200, "IA-64" },
|
||||||
{ 0x0266, "MIPS-16" },
|
{ 0x0266, "MIPS-16" },
|
||||||
{ 0x0284, "Alpha-64" },
|
{ 0x0284, "Alpha-64" },
|
||||||
|
|
@ -830,11 +877,11 @@ enum
|
||||||
kpidStackReserve,
|
kpidStackReserve,
|
||||||
kpidStackCommit,
|
kpidStackCommit,
|
||||||
kpidHeapReserve,
|
kpidHeapReserve,
|
||||||
kpidHeapCommit,
|
kpidHeapCommit
|
||||||
kpidImageBase
|
// , kpidImageBase
|
||||||
// kpidAddressOfEntryPoint,
|
// , kpidAddressOfEntryPoint
|
||||||
// kpidBaseOfCode,
|
// , kpidBaseOfCode
|
||||||
// kpidBaseOfData32,
|
// , kpidBaseOfData32
|
||||||
};
|
};
|
||||||
|
|
||||||
static const CStatProp kArcProps[] =
|
static const CStatProp kArcProps[] =
|
||||||
|
|
@ -864,14 +911,16 @@ static const CStatProp kArcProps[] =
|
||||||
{ "Stack Commit", kpidStackCommit, VT_UI8},
|
{ "Stack Commit", kpidStackCommit, VT_UI8},
|
||||||
{ "Heap Reserve", kpidHeapReserve, VT_UI8},
|
{ "Heap Reserve", kpidHeapReserve, VT_UI8},
|
||||||
{ "Heap Commit", kpidHeapCommit, VT_UI8},
|
{ "Heap Commit", kpidHeapCommit, VT_UI8},
|
||||||
{ "Image Base", kpidImageBase, VT_UI8},
|
{ NULL, kpidVa, VT_UI8 }, // "Image Base", kpidImageBase, VT_UI8
|
||||||
{ NULL, kpidComment, VT_BSTR},
|
{ NULL, kpidComment, VT_BSTR}
|
||||||
|
|
||||||
// { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
|
// , { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}
|
||||||
// { "Base Of Code", kpidBaseOfCode, VT_UI8},
|
// , { "Base Of Code", kpidBaseOfCode, VT_UI8}
|
||||||
// { "Base Of Data", kpidBaseOfData32, VT_UI8},
|
// , { "Base Of Data", kpidBaseOfData32, VT_UI8}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// #define kpid_NumRelocs 250
|
||||||
|
|
||||||
static const Byte kProps[] =
|
static const Byte kProps[] =
|
||||||
{
|
{
|
||||||
kpidPath,
|
kpidPath,
|
||||||
|
|
@ -880,7 +929,8 @@ static const Byte kProps[] =
|
||||||
kpidVirtualSize,
|
kpidVirtualSize,
|
||||||
kpidCharacts,
|
kpidCharacts,
|
||||||
kpidOffset,
|
kpidOffset,
|
||||||
kpidVa,
|
kpidVa
|
||||||
|
// , kpid_NumRelocs
|
||||||
};
|
};
|
||||||
|
|
||||||
IMP_IInArchive_Props
|
IMP_IInArchive_Props
|
||||||
|
|
@ -899,7 +949,42 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
switch (propID)
|
switch (propID)
|
||||||
{
|
{
|
||||||
case kpidPhySize: prop = _totalSize; break;
|
case kpidPhySize: prop = _totalSize; break;
|
||||||
case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break;
|
case kpidComment:
|
||||||
|
{
|
||||||
|
UString s (_versionFullString);
|
||||||
|
s.Add_LF();
|
||||||
|
s += "Data Directories: ";
|
||||||
|
s.Add_UInt32(_optHeader.NumDirItems);
|
||||||
|
s.Add_LF();
|
||||||
|
s.Add_Char('{');
|
||||||
|
s.Add_LF();
|
||||||
|
for (unsigned i = 0; i < _optHeader.NumDirItems
|
||||||
|
&& i < Z7_ARRAY_SIZE(_optHeader.DirItems); i++)
|
||||||
|
{
|
||||||
|
const CDirLink &di = _optHeader.DirItems[i];
|
||||||
|
if (di.Va == 0 && di.Size == 0)
|
||||||
|
continue;
|
||||||
|
s += "index=";
|
||||||
|
s.Add_UInt32(i);
|
||||||
|
|
||||||
|
if (i < Z7_ARRAY_SIZE(g_Dir_Names))
|
||||||
|
{
|
||||||
|
s += " name=";
|
||||||
|
s += g_Dir_Names[i];
|
||||||
|
}
|
||||||
|
s += " VA=0x";
|
||||||
|
char temp[16];
|
||||||
|
ConvertUInt32ToHex(di.Va, temp);
|
||||||
|
s += temp;
|
||||||
|
s += " Size=";
|
||||||
|
s.Add_UInt32(di.Size);
|
||||||
|
s.Add_LF();
|
||||||
|
}
|
||||||
|
s.Add_Char('}');
|
||||||
|
s.Add_LF();
|
||||||
|
prop = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kpidShortComment:
|
case kpidShortComment:
|
||||||
if (!_versionShortString.IsEmpty())
|
if (!_versionShortString.IsEmpty())
|
||||||
prop = _versionShortString;
|
prop = _versionShortString;
|
||||||
|
|
@ -969,8 +1054,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
case kpidStackCommit: prop = _optHeader.StackCommit; break;
|
case kpidStackCommit: prop = _optHeader.StackCommit; break;
|
||||||
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
|
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
|
||||||
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
|
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
|
||||||
|
case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:
|
||||||
case kpidImageBase: prop = _optHeader.ImageBase; break;
|
|
||||||
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
|
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
|
||||||
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
|
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
|
||||||
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
|
// case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
|
||||||
|
|
@ -1130,7 +1214,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||||
prop = MultiByteToUnicodeString(s);
|
prop = MultiByteToUnicodeString(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kpidSize: prop = (UInt64)item.PSize; break;
|
case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
|
||||||
|
// case kpid_NumRelocs: prop = (UInt32)item.NumRelocs; break;
|
||||||
case kpidPackSize: prop = (UInt64)item.PSize; break;
|
case kpidPackSize: prop = (UInt64)item.PSize; break;
|
||||||
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
|
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
|
||||||
case kpidOffset: prop = item.Pa; break;
|
case kpidOffset: prop = item.Pa; break;
|
||||||
|
|
@ -1229,7 +1314,7 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
|
||||||
sect.Time = de.Time;
|
sect.Time = de.Time;
|
||||||
sect.Va = de.Va;
|
sect.Va = de.Va;
|
||||||
sect.Pa = de.Pa;
|
sect.Pa = de.Pa;
|
||||||
sect.PSize = sect.VSize = de.Size;
|
sect.Set_Size_for_all(de.Size);
|
||||||
}
|
}
|
||||||
buf += kEntrySize;
|
buf += kEntrySize;
|
||||||
}
|
}
|
||||||
|
|
@ -1757,7 +1842,7 @@ static void CopyToUString(const Byte *p, UString &s)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
wchar_t c = (wchar_t)Get16(p);
|
const wchar_t c = (wchar_t)Get16(p);
|
||||||
p += 2;
|
p += 2;
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1765,6 +1850,16 @@ static void CopyToUString(const Byte *p, UString &s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CopyToUString_ByLen16(const Byte *p, unsigned numChars16, UString &s)
|
||||||
|
{
|
||||||
|
for (; numChars16; numChars16--)
|
||||||
|
{
|
||||||
|
const wchar_t c = (wchar_t)Get16(p);
|
||||||
|
p += 2;
|
||||||
|
s += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool CompareWStrStrings(const Byte *p, const char *s)
|
static bool CompareWStrStrings(const Byte *p, const char *s)
|
||||||
{
|
{
|
||||||
unsigned pos = 0;
|
unsigned pos = 0;
|
||||||
|
|
@ -1783,7 +1878,7 @@ struct CVersionBlock
|
||||||
{
|
{
|
||||||
UInt32 TotalLen;
|
UInt32 TotalLen;
|
||||||
UInt32 ValueLen;
|
UInt32 ValueLen;
|
||||||
bool IsTextValue;
|
unsigned IsTextValue;
|
||||||
unsigned StrSize;
|
unsigned StrSize;
|
||||||
|
|
||||||
bool Parse(const Byte *p, UInt32 size);
|
bool Parse(const Byte *p, UInt32 size);
|
||||||
|
|
@ -1802,6 +1897,23 @@ static int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Get_Utf16Str_Len_InBytes_AllowNonZeroTail(const Byte *p, size_t size)
|
||||||
|
{
|
||||||
|
unsigned pos = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pos + 1 >= size)
|
||||||
|
{
|
||||||
|
if (pos == size)
|
||||||
|
return (int)pos;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (Get16(p + pos) == 0)
|
||||||
|
return (int)pos;
|
||||||
|
pos += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const unsigned k_ResoureBlockHeader_Size = 6;
|
static const unsigned k_ResoureBlockHeader_Size = 6;
|
||||||
|
|
||||||
bool CVersionBlock::Parse(const Byte *p, UInt32 size)
|
bool CVersionBlock::Parse(const Byte *p, UInt32 size)
|
||||||
|
|
@ -1812,14 +1924,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
|
||||||
ValueLen = Get16(p + 2);
|
ValueLen = Get16(p + 2);
|
||||||
if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
|
if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
|
||||||
return false;
|
return false;
|
||||||
switch (Get16(p + 4))
|
IsTextValue = Get16(p + 4);
|
||||||
{
|
if (IsTextValue > 1)
|
||||||
case 0: IsTextValue = false; break;
|
return false;
|
||||||
case 1: IsTextValue = true; break;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
StrSize = 0;
|
StrSize = 0;
|
||||||
const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size);
|
const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size,
|
||||||
|
TotalLen - k_ResoureBlockHeader_Size);
|
||||||
if (t < 0)
|
if (t < 0)
|
||||||
return false;
|
return false;
|
||||||
StrSize = (unsigned)t;
|
StrSize = (unsigned)t;
|
||||||
|
|
@ -1859,7 +1969,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
// if (size != vb.TotalLen) return false;
|
// if (size != vb.TotalLen) return false;
|
||||||
*/
|
*/
|
||||||
if (size > vb.TotalLen)
|
if (size > vb.TotalLen)
|
||||||
size = vb.TotalLen;
|
size = vb.TotalLen;
|
||||||
CMy_VS_FIXEDFILEINFO FixedFileInfo;
|
CMy_VS_FIXEDFILEINFO FixedFileInfo;
|
||||||
if (!FixedFileInfo.Parse(p + pos))
|
if (!FixedFileInfo.Parse(p + pos))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1880,7 +1990,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
return false;
|
return false;
|
||||||
if (vb.ValueLen != 0)
|
if (vb.ValueLen != 0)
|
||||||
return false;
|
return false;
|
||||||
UInt32 endPos = pos + vb.TotalLen;
|
const UInt32 endPos = pos + vb.TotalLen;
|
||||||
pos += k_ResoureBlockHeader_Size;
|
pos += k_ResoureBlockHeader_Size;
|
||||||
|
|
||||||
f.AddSpaces(2);
|
f.AddSpaces(2);
|
||||||
|
|
@ -1901,7 +2011,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
CVersionBlock vb2;
|
CVersionBlock vb2;
|
||||||
if (!vb2.Parse(p + pos, endPos - pos))
|
if (!vb2.Parse(p + pos, endPos - pos))
|
||||||
return false;
|
return false;
|
||||||
UInt32 endPos2 = pos + vb2.TotalLen;
|
const UInt32 endPos2 = pos + vb2.TotalLen;
|
||||||
if (vb2.IsTextValue)
|
if (vb2.IsTextValue)
|
||||||
return false;
|
return false;
|
||||||
pos += k_ResoureBlockHeader_Size;
|
pos += k_ResoureBlockHeader_Size;
|
||||||
|
|
@ -1919,9 +2029,9 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
UInt32 num = (vb2.ValueLen >> 2);
|
UInt32 num = (vb2.ValueLen >> 2);
|
||||||
for (; num != 0; num--, pos += 4)
|
for (; num != 0; num--, pos += 4)
|
||||||
{
|
{
|
||||||
UInt32 dw = Get32(p + pos);
|
const UInt32 dw = Get32(p + pos);
|
||||||
UInt32 lang = LOWORD(dw);
|
const UInt32 lang = LOWORD(dw);
|
||||||
UInt32 codePage = HIWORD(dw);
|
const UInt32 codePage = HIWORD(dw);
|
||||||
|
|
||||||
f.AddString(", ");
|
f.AddString(", ");
|
||||||
PrintHex(f, lang);
|
PrintHex(f, lang);
|
||||||
|
|
@ -1936,7 +2046,6 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
if (!CompareWStrStrings(p + pos, "StringFileInfo"))
|
if (!CompareWStrStrings(p + pos, "StringFileInfo"))
|
||||||
return false;
|
return false;
|
||||||
pos += vb.StrSize + 2;
|
pos += vb.StrSize + 2;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
pos += (4 - pos) & 3;
|
pos += (4 - pos) & 3;
|
||||||
|
|
@ -1945,7 +2054,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
CVersionBlock vb2;
|
CVersionBlock vb2;
|
||||||
if (!vb2.Parse(p + pos, endPos - pos))
|
if (!vb2.Parse(p + pos, endPos - pos))
|
||||||
return false;
|
return false;
|
||||||
UInt32 endPos2 = pos + vb2.TotalLen;
|
const UInt32 endPos2 = pos + vb2.TotalLen;
|
||||||
if (vb2.ValueLen != 0)
|
if (vb2.ValueLen != 0)
|
||||||
return false;
|
return false;
|
||||||
pos += k_ResoureBlockHeader_Size;
|
pos += k_ResoureBlockHeader_Size;
|
||||||
|
|
@ -1967,9 +2076,8 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
CVersionBlock vb3;
|
CVersionBlock vb3;
|
||||||
if (!vb3.Parse(p + pos, endPos2 - pos))
|
if (!vb3.Parse(p + pos, endPos2 - pos))
|
||||||
return false;
|
return false;
|
||||||
// ValueLen sometimes is a number of characters (not bytes)?
|
// ValueLen is a number of 16-bit characters (usually it includes zero tail character).
|
||||||
// So we don't use it.
|
const UInt32 endPos3 = pos + vb3.TotalLen;
|
||||||
UInt32 endPos3 = pos + vb3.TotalLen;
|
|
||||||
pos += k_ResoureBlockHeader_Size;
|
pos += k_ResoureBlockHeader_Size;
|
||||||
|
|
||||||
// we don't write string if it's not text
|
// we don't write string if it's not text
|
||||||
|
|
@ -1984,26 +2092,35 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
|
||||||
pos += vb3.StrSize + 2;
|
pos += vb3.StrSize + 2;
|
||||||
|
|
||||||
pos += (4 - pos) & 3;
|
pos += (4 - pos) & 3;
|
||||||
if (vb3.ValueLen > 0 && pos + 2 <= endPos3)
|
if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)
|
||||||
{
|
{
|
||||||
f.AddChar(',');
|
f.AddChar(',');
|
||||||
f.AddSpaces((34 - (int)vb3.StrSize) / 2);
|
f.AddSpaces((34 - (int)vb3.StrSize) / 2);
|
||||||
const int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos);
|
// vb3.TotalLen for some PE files (not from msvc) doesn't include tail zero at the end of Value string.
|
||||||
|
// we allow that minor error.
|
||||||
|
const int sLen = Get_Utf16Str_Len_InBytes_AllowNonZeroTail(p + pos, endPos3 - pos);
|
||||||
if (sLen < 0)
|
if (sLen < 0)
|
||||||
return false;
|
return false;
|
||||||
|
/*
|
||||||
|
if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&
|
||||||
|
vb3.ValueLen != (unsigned)sLen / 2)
|
||||||
|
return false;
|
||||||
|
*/
|
||||||
AddParamString(f, p + pos, (unsigned)sLen);
|
AddParamString(f, p + pos, (unsigned)sLen);
|
||||||
CopyToUString(p + pos, value);
|
CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);
|
||||||
pos += (unsigned)sLen + 2;
|
// pos += (unsigned)sLen + 2;
|
||||||
}
|
}
|
||||||
AddToUniqueUStringVector(keys, key, value);
|
AddToUniqueUStringVector(keys, key, value);
|
||||||
}
|
}
|
||||||
pos = endPos3;
|
pos = endPos3;
|
||||||
f.NewLine();
|
f.NewLine();
|
||||||
}
|
}
|
||||||
|
pos = endPos2;
|
||||||
f.CloseBlock(4);
|
f.CloseBlock(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.CloseBlock(2);
|
f.CloseBlock(2);
|
||||||
|
pos = endPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.CloseBlock(0);
|
f.CloseBlock(0);
|
||||||
|
|
@ -2218,7 +2335,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
|
||||||
|
|
||||||
if (sect2.PSize != 0)
|
if (sect2.PSize != 0)
|
||||||
{
|
{
|
||||||
sect2.VSize = sect2.PSize;
|
sect2.ExtractSize = sect2.VSize = sect2.PSize;
|
||||||
sect2.Name = ".rsrc_1";
|
sect2.Name = ".rsrc_1";
|
||||||
sect2.Time = 0;
|
sect2.Time = 0;
|
||||||
sect2.IsAdditionalSection = true;
|
sect2.IsAdditionalSection = true;
|
||||||
|
|
@ -2337,6 +2454,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||||
CSection § = _sections.AddNew();
|
CSection § = _sections.AddNew();
|
||||||
sect.Parse(buffer + pos);
|
sect.Parse(buffer + pos);
|
||||||
sect.IsRealSect = true;
|
sect.IsRealSect = true;
|
||||||
|
if (sect.Name.IsEqualTo(".reloc"))
|
||||||
|
{
|
||||||
|
const CDirLink &dl = _optHeader.DirItems[kDirLink_BASERELOC];
|
||||||
|
if (dl.Va == sect.Va &&
|
||||||
|
dl.Size <= sect.PSize)
|
||||||
|
sect.ExtractSize = dl.Size;
|
||||||
|
}
|
||||||
|
else if (sect.Name.IsEqualTo(".pdata"))
|
||||||
|
{
|
||||||
|
const CDirLink &dl = _optHeader.DirItems[kDirLink_EXCEPTION];
|
||||||
|
if (dl.Va == sect.Va &&
|
||||||
|
dl.Size <= sect.PSize)
|
||||||
|
sect.ExtractSize = dl.Size;
|
||||||
|
}
|
||||||
|
|
||||||
/* PE pre-file in .hxs file has errors:
|
/* PE pre-file in .hxs file has errors:
|
||||||
PSize of resource is larger than real size.
|
PSize of resource is larger than real size.
|
||||||
|
|
@ -2390,7 +2521,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||||
sect.Name = "CERTIFICATE";
|
sect.Name = "CERTIFICATE";
|
||||||
sect.Va = 0;
|
sect.Va = 0;
|
||||||
sect.Pa = certLink.Va;
|
sect.Pa = certLink.Va;
|
||||||
sect.PSize = sect.VSize = certLink.Size;
|
sect.Set_Size_for_all(certLink.Size);
|
||||||
sect.UpdateTotalSize(_totalSize);
|
sect.UpdateTotalSize(_totalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2448,7 +2579,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||||
sect.Name = "COFF_SYMBOLS";
|
sect.Name = "COFF_SYMBOLS";
|
||||||
sect.Va = 0;
|
sect.Va = 0;
|
||||||
sect.Pa = _header.PointerToSymbolTable;
|
sect.Pa = _header.PointerToSymbolTable;
|
||||||
sect.PSize = sect.VSize = size;
|
sect.Set_Size_for_all(size);
|
||||||
sect.UpdateTotalSize(_totalSize);
|
sect.UpdateTotalSize(_totalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2464,11 +2595,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
|
||||||
{
|
{
|
||||||
CSection &s2 = _sections.AddNew();
|
CSection &s2 = _sections.AddNew();
|
||||||
s2.Pa = s2.Va = limit;
|
s2.Pa = s2.Va = limit;
|
||||||
s2.PSize = s2.VSize = s.Pa - limit;
|
s2.Set_Size_for_all(s.Pa - limit);
|
||||||
s2.IsAdditionalSection = true;
|
s2.IsAdditionalSection = true;
|
||||||
s2.Name = '[';
|
s2.Name.Add_Char('[');
|
||||||
s2.Name.Add_UInt32(num++);
|
s2.Name.Add_UInt32(num++);
|
||||||
s2.Name += ']';
|
s2.Name.Add_Char(']');
|
||||||
limit = s.Pa;
|
limit = s.Pa;
|
||||||
}
|
}
|
||||||
UInt32 next = s.Pa + s.PSize;
|
UInt32 next = s.Pa + s.PSize;
|
||||||
|
|
@ -2700,29 +2831,26 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||||
else if (mixItem.ResourceIndex >= 0)
|
else if (mixItem.ResourceIndex >= 0)
|
||||||
size = _items[mixItem.ResourceIndex].GetSize();
|
size = _items[mixItem.ResourceIndex].GetSize();
|
||||||
else
|
else
|
||||||
size = _sections[mixItem.SectionIndex].GetSizeExtract();
|
size = _sections[mixItem.SectionIndex].GetSize_Extract();
|
||||||
totalSize += size;
|
totalSize += size;
|
||||||
}
|
}
|
||||||
extractCallback->SetTotal(totalSize);
|
RINOK(extractCallback->SetTotal(totalSize))
|
||||||
|
|
||||||
UInt64 currentTotalSize = 0;
|
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||||
|
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||||
|
lps->Init(extractCallback, false);
|
||||||
|
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
|
||||||
|
inStream->SetStream(_stream);
|
||||||
|
|
||||||
|
totalSize = 0;
|
||||||
UInt64 currentItemSize;
|
UInt64 currentItemSize;
|
||||||
|
|
||||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
for (i = 0;; i++, totalSize += currentItemSize)
|
||||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
|
||||||
lps->Init(extractCallback, false);
|
|
||||||
|
|
||||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
|
||||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
|
||||||
streamSpec->SetStream(_stream);
|
|
||||||
|
|
||||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
|
||||||
{
|
{
|
||||||
lps->InSize = lps->OutSize = currentTotalSize;
|
lps->InSize = lps->OutSize = totalSize;
|
||||||
RINOK(lps->SetCur())
|
RINOK(lps->SetCur())
|
||||||
|
if (i >= numItems)
|
||||||
|
break;
|
||||||
const Int32 askMode = testMode ?
|
const Int32 askMode = testMode ?
|
||||||
NExtract::NAskMode::kTest :
|
NExtract::NAskMode::kTest :
|
||||||
NExtract::NAskMode::kExtract;
|
NExtract::NAskMode::kExtract;
|
||||||
|
|
@ -2776,15 +2904,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentItemSize = sect.GetSizeExtract();
|
currentItemSize = sect.GetSize_Extract();
|
||||||
if (!testMode && !outStream)
|
if (!testMode && !outStream)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
RINOK(extractCallback->PrepareOperation(askMode))
|
RINOK(extractCallback->PrepareOperation(askMode))
|
||||||
RINOK(InStream_SeekSet(_stream, sect.Pa))
|
RINOK(InStream_SeekSet(_stream, sect.Pa))
|
||||||
streamSpec->Init(currentItemSize);
|
inStream->Init(currentItemSize);
|
||||||
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
|
RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
|
||||||
isOk = (copyCoderSpec->TotalSize == currentItemSize);
|
isOk = (copyCoder->TotalSize == currentItemSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
outStream.Release();
|
outStream.Release();
|
||||||
|
|
@ -2804,7 +2932,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||||
const CMixItem &mixItem = _mixItems[index];
|
const CMixItem &mixItem = _mixItems[index];
|
||||||
const CSection § = _sections[mixItem.SectionIndex];
|
const CSection § = _sections[mixItem.SectionIndex];
|
||||||
if (mixItem.IsSectionItem())
|
if (mixItem.IsSectionItem())
|
||||||
return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream);
|
return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);
|
||||||
|
|
||||||
CBufInStream *inStreamSpec = new CBufInStream;
|
CBufInStream *inStreamSpec = new CBufInStream;
|
||||||
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
|
||||||
|
|
@ -2964,7 +3092,7 @@ bool CHeader::Parse(const Byte *p)
|
||||||
G32(12, BaseOfCode);
|
G32(12, BaseOfCode);
|
||||||
G64(16, ImageBase);
|
G64(16, ImageBase);
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < 2; i++)
|
for (unsigned i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
CDataDir &dd = DataDir[i];
|
CDataDir &dd = DataDir[i];
|
||||||
dd.Parse(p + 24 + i * 8);
|
dd.Parse(p + 24 + i * 8);
|
||||||
|
|
@ -2997,6 +3125,7 @@ struct CSection
|
||||||
{
|
{
|
||||||
Byte Name[NPe::kNameSize];
|
Byte Name[NPe::kNameSize];
|
||||||
|
|
||||||
|
UInt32 ExtractSize;
|
||||||
UInt32 VSize;
|
UInt32 VSize;
|
||||||
UInt32 Va;
|
UInt32 Va;
|
||||||
UInt32 PSize;
|
UInt32 PSize;
|
||||||
|
|
@ -3013,6 +3142,7 @@ struct CSection
|
||||||
G32(20, Pa);
|
G32(20, Pa);
|
||||||
// G32(p + 32, NumRelocs);
|
// G32(p + 32, NumRelocs);
|
||||||
G32(36, Flags);
|
G32(36, Flags);
|
||||||
|
ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Check() const
|
bool Check() const
|
||||||
|
|
@ -3022,11 +3152,16 @@ struct CSection
|
||||||
PSize <= ((UInt32)1 << 30);
|
PSize <= ((UInt32)1 << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32 GetSize_Extract() const
|
||||||
|
{
|
||||||
|
return ExtractSize;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateTotalSize(UInt32 &totalSize)
|
void UpdateTotalSize(UInt32 &totalSize)
|
||||||
{
|
{
|
||||||
UInt32 t = Pa + PSize;
|
const UInt32 t = Pa + PSize;
|
||||||
if (t > totalSize)
|
if (totalSize < t)
|
||||||
totalSize = t;
|
totalSize = t;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -3050,6 +3185,7 @@ static const Byte kProps[] =
|
||||||
{
|
{
|
||||||
kpidPath,
|
kpidPath,
|
||||||
kpidSize,
|
kpidSize,
|
||||||
|
kpidPackSize,
|
||||||
kpidVirtualSize,
|
kpidVirtualSize,
|
||||||
kpidCharacts,
|
kpidCharacts,
|
||||||
kpidOffset,
|
kpidOffset,
|
||||||
|
|
@ -3108,7 +3244,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
||||||
prop = MultiByteToUnicodeString(name);
|
prop = MultiByteToUnicodeString(name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kpidSize:
|
case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
|
||||||
case kpidPackSize: prop = (UInt64)item.PSize; break;
|
case kpidPackSize: prop = (UInt64)item.PSize; break;
|
||||||
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
|
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
|
||||||
case kpidOffset: prop = item.Pa; break;
|
case kpidOffset: prop = item.Pa; break;
|
||||||
|
|
@ -3168,13 +3304,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
Close();
|
Close();
|
||||||
try
|
// try
|
||||||
{
|
{
|
||||||
if (Open2(inStream) != S_OK)
|
if (Open2(inStream) != S_OK)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
_stream = inStream;
|
_stream = inStream;
|
||||||
}
|
}
|
||||||
catch(...) { return S_FALSE; }
|
// catch(...) { return S_FALSE; }
|
||||||
return S_OK;
|
return S_OK;
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
@ -3205,26 +3341,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||||
UInt64 totalSize = 0;
|
UInt64 totalSize = 0;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < numItems; i++)
|
for (i = 0; i < numItems; i++)
|
||||||
totalSize += _items[allFilesMode ? i : indices[i]].PSize;
|
totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();
|
||||||
extractCallback->SetTotal(totalSize);
|
RINOK(extractCallback->SetTotal(totalSize))
|
||||||
|
|
||||||
UInt64 currentTotalSize = 0;
|
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
|
||||||
|
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
|
||||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
|
||||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
|
||||||
lps->Init(extractCallback, false);
|
lps->Init(extractCallback, false);
|
||||||
|
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
|
||||||
|
inStream->SetStream(_stream);
|
||||||
|
|
||||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
totalSize = 0;
|
||||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
|
||||||
streamSpec->SetStream(_stream);
|
|
||||||
|
|
||||||
for (i = 0; i < numItems; i++)
|
for (i = 0;; i++)
|
||||||
{
|
{
|
||||||
lps->InSize = lps->OutSize = currentTotalSize;
|
lps->InSize = lps->OutSize = totalSize;
|
||||||
RINOK(lps->SetCur())
|
RINOK(lps->SetCur())
|
||||||
|
if (i >= numItems)
|
||||||
|
break;
|
||||||
|
int opRes;
|
||||||
|
{
|
||||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||||
const Int32 askMode = testMode ?
|
const Int32 askMode = testMode ?
|
||||||
NExtract::NAskMode::kTest :
|
NExtract::NAskMode::kTest :
|
||||||
|
|
@ -3232,21 +3367,22 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
|
||||||
const UInt32 index = allFilesMode ? i : indices[i];
|
const UInt32 index = allFilesMode ? i : indices[i];
|
||||||
const CSection &item = _items[index];
|
const CSection &item = _items[index];
|
||||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
|
||||||
currentTotalSize += item.PSize;
|
const UInt32 size = item.GetSize_Extract();
|
||||||
|
totalSize += size;
|
||||||
|
|
||||||
if (!testMode && !realOutStream)
|
if (!testMode && !realOutStream)
|
||||||
continue;
|
continue;
|
||||||
RINOK(extractCallback->PrepareOperation(askMode))
|
RINOK(extractCallback->PrepareOperation(askMode))
|
||||||
int res = NExtract::NOperationResult::kDataError;
|
|
||||||
|
|
||||||
RINOK(InStream_SeekSet(_stream, item.Pa))
|
RINOK(InStream_SeekSet(_stream, item.Pa))
|
||||||
streamSpec->Init(item.PSize);
|
inStream->Init(size);
|
||||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress))
|
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
|
||||||
if (copyCoderSpec->TotalSize == item.PSize)
|
|
||||||
res = NExtract::NOperationResult::kOK;
|
|
||||||
|
|
||||||
realOutStream.Release();
|
opRes = (copyCoder->TotalSize == size) ?
|
||||||
RINOK(extractCallback->SetOperationResult(res))
|
NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?
|
||||||
|
NExtract::NOperationResult::kUnexpectedEnd :
|
||||||
|
NExtract::NOperationResult::kDataError;
|
||||||
|
}
|
||||||
|
RINOK(extractCallback->SetOperationResult(opRes))
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
|
|
@ -3256,7 +3392,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
const CSection &item = _items[index];
|
const CSection &item = _items[index];
|
||||||
return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream);
|
return CreateLimitedInStream(_stream, item.Pa, item.GetSize_Extract(), stream);
|
||||||
COM_TRY_END
|
COM_TRY_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "../../Common/MyBuffer2.h"
|
#include "../../Common/MyBuffer2.h"
|
||||||
|
|
||||||
#include "../../Windows/PropVariant.h"
|
#include "../../Windows/PropVariant.h"
|
||||||
|
#include "../../Windows/PropVariantUtils.h"
|
||||||
|
|
||||||
#include "../Common/RegisterArc.h"
|
#include "../Common/RegisterArc.h"
|
||||||
#include "../Common/StreamObjects.h"
|
#include "../Common/StreamObjects.h"
|
||||||
|
|
@ -20,8 +21,8 @@
|
||||||
|
|
||||||
#include "HandlerCont.h"
|
#include "HandlerCont.h"
|
||||||
|
|
||||||
#define Get32(p) GetBe32(p)
|
#define Get32(p) GetBe32a(p)
|
||||||
#define Get64(p) GetBe64(p)
|
#define Get64(p) GetBe64a(p)
|
||||||
|
|
||||||
using namespace NWindows;
|
using namespace NWindows;
|
||||||
|
|
||||||
|
|
@ -32,9 +33,9 @@ static const Byte k_Signature[] = { 'Q', 'F', 'I', 0xFB, 0, 0, 0 };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
VA to PA maps:
|
VA to PA maps:
|
||||||
high bits (L1) : : in L1 Table : the reference to L1 Table
|
high bits (L1) : : index in L1 (_dir) : _dir[high_index] points to Table.
|
||||||
mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster
|
mid bits (L2) : _numMidBits : index in Table, Table[index] points to cluster start offset in arc file.
|
||||||
low bits : _clusterBits
|
low bits : _clusterBits : offset inside cluster.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Z7_class_CHandler_final: public CHandlerImg
|
Z7_class_CHandler_final: public CHandlerImg
|
||||||
|
|
@ -49,30 +50,27 @@ Z7_class_CHandler_final: public CHandlerImg
|
||||||
|
|
||||||
CObjArray2<UInt32> _dir;
|
CObjArray2<UInt32> _dir;
|
||||||
CAlignedBuffer _table;
|
CAlignedBuffer _table;
|
||||||
UInt64 _cacheCluster;
|
|
||||||
CByteBuffer _cache;
|
CByteBuffer _cache;
|
||||||
CByteBuffer _cacheCompressed;
|
CByteBuffer _cacheCompressed;
|
||||||
|
UInt64 _cacheCluster;
|
||||||
|
|
||||||
UInt64 _comprPos;
|
UInt64 _comprPos;
|
||||||
size_t _comprSize;
|
size_t _comprSize;
|
||||||
|
|
||||||
UInt64 _phySize;
|
bool _needCompression;
|
||||||
|
|
||||||
CBufInStream *_bufInStreamSpec;
|
|
||||||
CMyComPtr<ISequentialInStream> _bufInStream;
|
|
||||||
|
|
||||||
CBufPtrSeqOutStream *_bufOutStreamSpec;
|
|
||||||
CMyComPtr<ISequentialOutStream> _bufOutStream;
|
|
||||||
|
|
||||||
NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoderSpec;
|
|
||||||
CMyComPtr<ICompressCoder> _deflateDecoder;
|
|
||||||
|
|
||||||
bool _needDeflate;
|
|
||||||
bool _isArc;
|
bool _isArc;
|
||||||
bool _unsupported;
|
bool _unsupported;
|
||||||
|
Byte _compressionType;
|
||||||
|
|
||||||
|
UInt64 _phySize;
|
||||||
|
|
||||||
|
CMyComPtr2<ISequentialInStream, CBufInStream> _bufInStream;
|
||||||
|
CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> _bufOutStream;
|
||||||
|
CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> _deflateDecoder;
|
||||||
|
|
||||||
UInt32 _version;
|
UInt32 _version;
|
||||||
UInt32 _cryptMethod;
|
UInt32 _cryptMethod;
|
||||||
|
UInt64 _incompatFlags;
|
||||||
|
|
||||||
HRESULT Seek2(UInt64 offset)
|
HRESULT Seek2(UInt64 offset)
|
||||||
{
|
{
|
||||||
|
|
@ -96,13 +94,11 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
{
|
{
|
||||||
if (processedSize)
|
if (processedSize)
|
||||||
*processedSize = 0;
|
*processedSize = 0;
|
||||||
|
|
||||||
// printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
|
// printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
|
||||||
|
|
||||||
if (_virtPos >= _size)
|
if (_virtPos >= _size)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
{
|
{
|
||||||
UInt64 rem = _size - _virtPos;
|
const UInt64 rem = _size - _virtPos;
|
||||||
if (size > rem)
|
if (size > rem)
|
||||||
size = (UInt32)rem;
|
size = (UInt32)rem;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
|
@ -115,11 +111,10 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
const size_t clusterSize = (size_t)1 << _clusterBits;
|
const size_t clusterSize = (size_t)1 << _clusterBits;
|
||||||
const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
|
const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
|
||||||
{
|
{
|
||||||
size_t rem = clusterSize - lowBits;
|
const size_t rem = clusterSize - lowBits;
|
||||||
if (size > rem)
|
if (size > rem)
|
||||||
size = (UInt32)rem;
|
size = (UInt32)rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cluster == _cacheCluster)
|
if (cluster == _cacheCluster)
|
||||||
{
|
{
|
||||||
memcpy(data, _cache + lowBits, size);
|
memcpy(data, _cache + lowBits, size);
|
||||||
|
|
@ -130,32 +125,29 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
|
|
||||||
if (high < _dir.Size())
|
if (high < _dir.Size())
|
||||||
{
|
{
|
||||||
const UInt32 tabl = _dir[(unsigned)high];
|
const UInt32 tabl = _dir[(size_t)high];
|
||||||
|
|
||||||
if (tabl != kEmptyDirItem)
|
if (tabl != kEmptyDirItem)
|
||||||
{
|
{
|
||||||
const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3));
|
|
||||||
const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
|
const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
|
||||||
const Byte *p = (const Byte *)buffer + (midBits << 3);
|
const Byte *p = _table + ((((size_t)tabl << _numMidBits) + midBits) << 3);
|
||||||
UInt64 v = Get64(p);
|
UInt64 v = Get64(p);
|
||||||
|
|
||||||
if (v != 0)
|
if (v)
|
||||||
{
|
{
|
||||||
if ((v & _compressedFlag) != 0)
|
if (v & _compressedFlag)
|
||||||
{
|
{
|
||||||
if (_version <= 1)
|
if (_version <= 1)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
the example of table record for 12-bit clusters (4KB uncompressed).
|
the example of table record for 12-bit clusters (4KB uncompressed):
|
||||||
2 bits : isCompressed status
|
2 bits : isCompressed status
|
||||||
4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512;
|
(4 == _clusterBits - 8) bits : (num_sectors - 1)
|
||||||
it uses one additional bit over unpacked cluster_bits
|
packSize = num_sectors * 512;
|
||||||
49 bits : offset of 512-sector
|
it uses one additional bit over unpacked cluster_bits.
|
||||||
9 bits : offset in 512-sector
|
(49 == 61 - _clusterBits) bits : offset of 512-byte sector
|
||||||
|
9 bits : offset in 512-byte sector
|
||||||
*/
|
*/
|
||||||
|
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
|
||||||
const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1));
|
|
||||||
const UInt64 offset = v & (((UInt64)1 << 62) - 1);
|
const UInt64 offset = v & (((UInt64)1 << 62) - 1);
|
||||||
const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
||||||
UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));
|
UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));
|
||||||
|
|
@ -167,7 +159,7 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
|
|
||||||
if (sectorOffset >= _comprPos && offset2inCache < _comprSize)
|
if (sectorOffset >= _comprPos && offset2inCache < _comprSize)
|
||||||
{
|
{
|
||||||
if (offset2inCache != 0)
|
if (offset2inCache)
|
||||||
{
|
{
|
||||||
_comprSize -= (size_t)offset2inCache;
|
_comprSize -= (size_t)offset2inCache;
|
||||||
memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);
|
memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);
|
||||||
|
|
@ -193,39 +185,34 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
const size_t dataSize3 = dataSize - _comprSize;
|
const size_t dataSize3 = dataSize - _comprSize;
|
||||||
size_t dataSize2 = dataSize3;
|
size_t dataSize2 = dataSize3;
|
||||||
// printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos);
|
// printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos);
|
||||||
RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2))
|
const HRESULT hres = ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2);
|
||||||
_posInArc += dataSize2;
|
_posInArc += dataSize2;
|
||||||
|
RINOK(hres)
|
||||||
if (dataSize2 != dataSize3)
|
if (dataSize2 != dataSize3)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
_comprSize += dataSize2;
|
_comprSize += dataSize2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t kSectorMask = (1 << 9) - 1;
|
const size_t kSectorMask = (1 << 9) - 1;
|
||||||
const size_t offsetInSector = ((size_t)offset & kSectorMask);
|
const size_t offsetInSector = (size_t)offset & kSectorMask;
|
||||||
_bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
|
_bufInStream->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
|
||||||
|
|
||||||
_cacheCluster = (UInt64)(Int64)-1;
|
_cacheCluster = (UInt64)(Int64)-1;
|
||||||
if (_cache.Size() < clusterSize)
|
if (_cache.Size() < clusterSize)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
_bufOutStreamSpec->Init(_cache, clusterSize);
|
_bufOutStream->Init(_cache, clusterSize);
|
||||||
|
|
||||||
// Do we need to use smaller block than clusterSize for last cluster?
|
// Do we need to use smaller block than clusterSize for last cluster?
|
||||||
const UInt64 blockSize64 = clusterSize;
|
const UInt64 blockSize64 = clusterSize;
|
||||||
HRESULT res = _deflateDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
|
HRESULT res = _deflateDecoder.Interface()->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (_bufOutStreamSpec->GetPos() != clusterSize)
|
if (_bufOutStreamSpec->GetPos() != clusterSize)
|
||||||
memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
|
memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (res == S_OK)
|
if (res == S_OK)
|
||||||
if (!_deflateDecoderSpec->IsFinished()
|
if (!_deflateDecoder->IsFinished()
|
||||||
|| _bufOutStreamSpec->GetPos() != clusterSize)
|
|| _bufOutStream->GetPos() != clusterSize)
|
||||||
res = S_FALSE;
|
res = S_FALSE;
|
||||||
|
|
||||||
RINOK(res)
|
RINOK(res)
|
||||||
_cacheCluster = cluster;
|
_cacheCluster = cluster;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
memcpy(data, _cache + lowBits, size);
|
memcpy(data, _cache + lowBits, size);
|
||||||
|
|
@ -233,17 +220,17 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// version 3 support zero clusters
|
// version_3 supports zero clusters
|
||||||
if (((UInt32)v & 511) != 1)
|
if (((UInt32)v & 511) != 1)
|
||||||
{
|
{
|
||||||
v &= (_compressedFlag - 1);
|
v &= _compressedFlag - 1;
|
||||||
v += lowBits;
|
v += lowBits;
|
||||||
if (v != _posInArc)
|
if (v != _posInArc)
|
||||||
{
|
{
|
||||||
// printf("\n%12I64x\n", v - _posInArc);
|
// printf("\n%12I64x\n", v - _posInArc);
|
||||||
RINOK(Seek2(v))
|
RINOK(Seek2(v))
|
||||||
}
|
}
|
||||||
HRESULT res = Stream->Read(data, size, &size);
|
const HRESULT res = Stream->Read(data, size, &size);
|
||||||
_posInArc += size;
|
_posInArc += size;
|
||||||
_virtPos += size;
|
_virtPos += size;
|
||||||
if (processedSize)
|
if (processedSize)
|
||||||
|
|
@ -274,13 +261,25 @@ static const Byte kProps[] =
|
||||||
static const Byte kArcProps[] =
|
static const Byte kArcProps[] =
|
||||||
{
|
{
|
||||||
kpidClusterSize,
|
kpidClusterSize,
|
||||||
|
kpidSectorSize, // actually we need variable to show table size
|
||||||
|
kpidHeadersSize,
|
||||||
kpidUnpackVer,
|
kpidUnpackVer,
|
||||||
kpidMethod
|
kpidMethod,
|
||||||
|
kpidCharacts
|
||||||
};
|
};
|
||||||
|
|
||||||
IMP_IInArchive_Props
|
IMP_IInArchive_Props
|
||||||
IMP_IInArchive_ArcProps
|
IMP_IInArchive_ArcProps
|
||||||
|
|
||||||
|
static const CUInt32PCharPair g_IncompatFlags_Characts[] =
|
||||||
|
{
|
||||||
|
{ 0, "Dirty" },
|
||||||
|
{ 1, "Corrupt" },
|
||||||
|
{ 2, "External_Data_File" },
|
||||||
|
{ 3, "Compression" },
|
||||||
|
{ 4, "Extended_L2" }
|
||||||
|
};
|
||||||
|
|
||||||
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
|
|
@ -290,28 +289,54 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
{
|
{
|
||||||
case kpidMainSubfile: prop = (UInt32)0; break;
|
case kpidMainSubfile: prop = (UInt32)0; break;
|
||||||
case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;
|
case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;
|
||||||
case kpidPhySize: if (_phySize != 0) prop = _phySize; break;
|
case kpidSectorSize: prop = (UInt32)1 << (_numMidBits + 3); break;
|
||||||
|
case kpidHeadersSize: prop = _table.Size() + (UInt64)_dir.Size() * 8; break;
|
||||||
|
case kpidPhySize: if (_phySize) prop = _phySize; break;
|
||||||
case kpidUnpackVer: prop = _version; break;
|
case kpidUnpackVer: prop = _version; break;
|
||||||
|
case kpidCharacts:
|
||||||
|
{
|
||||||
|
if (_incompatFlags)
|
||||||
|
{
|
||||||
|
AString s ("incompatible: ");
|
||||||
|
// we need to show also high 32-bits.
|
||||||
|
s += FlagsToString(g_IncompatFlags_Characts,
|
||||||
|
Z7_ARRAY_SIZE(g_IncompatFlags_Characts), (UInt32)_incompatFlags);
|
||||||
|
prop = s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case kpidMethod:
|
case kpidMethod:
|
||||||
{
|
{
|
||||||
AString s;
|
AString s;
|
||||||
|
|
||||||
if (_needDeflate)
|
if (_compressionType)
|
||||||
s = "Deflate";
|
{
|
||||||
|
if (_compressionType == 1)
|
||||||
|
s += "ZSTD";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s += "Compression:";
|
||||||
|
s.Add_UInt32(_compressionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_needCompression)
|
||||||
|
s.Add_OptSpaced("Deflate");
|
||||||
|
|
||||||
if (_cryptMethod != 0)
|
if (_cryptMethod)
|
||||||
{
|
{
|
||||||
s.Add_Space_if_NotEmpty();
|
s.Add_Space_if_NotEmpty();
|
||||||
if (_cryptMethod == 1)
|
if (_cryptMethod == 1)
|
||||||
s += "AES";
|
s += "AES";
|
||||||
|
if (_cryptMethod == 2)
|
||||||
|
s += "LUKS";
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
s += "Encryption:";
|
||||||
s.Add_UInt32(_cryptMethod);
|
s.Add_UInt32(_cryptMethod);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s.IsEmpty())
|
if (!s.IsEmpty())
|
||||||
prop = s;
|
prop = s;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,9 +346,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
|
||||||
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
|
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
|
||||||
// if (_headerError) v |= kpv_ErrorFlags_HeadersError;
|
// if (_headerError) v |= kpv_ErrorFlags_HeadersError;
|
||||||
if (!Stream && v == 0 && _isArc)
|
if (!Stream && v == 0)
|
||||||
v = kpv_ErrorFlags_HeadersError;
|
v = kpv_ErrorFlags_HeadersError;
|
||||||
if (v != 0)
|
if (v)
|
||||||
prop = v;
|
prop = v;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -355,76 +380,91 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
|
||||||
|
|
||||||
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||||
{
|
{
|
||||||
const unsigned kHeaderSize = 18 * 4;
|
UInt64 buf64[0x70 / 8];
|
||||||
Byte buf[kHeaderSize];
|
RINOK(ReadStream_FALSE(stream, buf64, sizeof(buf64)))
|
||||||
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))
|
const void *buf = (const void *)buf64;
|
||||||
|
// signature: { 'Q', 'F', 'I', 0xFB }
|
||||||
if (memcmp(buf, k_Signature, 4) != 0)
|
if (*(const UInt32 *)buf != Z7_CONV_BE_TO_NATIVE_CONST32(0x514649fb))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
_version = Get32((const Byte *)(const void *)buf64 + 4);
|
||||||
_version = Get32(buf + 4);
|
|
||||||
if (_version < 1 || _version > 3)
|
if (_version < 1 || _version > 3)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
const UInt64 backOffset = Get64(buf + 8);
|
const UInt64 k_UncompressedSize_MAX = (UInt64)1 << 60;
|
||||||
// UInt32 backSize = Get32(buf + 0x10);
|
const UInt64 k_CompressedSize_MAX = (UInt64)1 << 60;
|
||||||
|
|
||||||
UInt64 l1Offset;
|
_size = Get64((const Byte *)(const void *)buf64 + 0x18);
|
||||||
UInt32 l1Size;
|
if (_size > k_UncompressedSize_MAX)
|
||||||
|
return S_FALSE;
|
||||||
|
size_t l1Size;
|
||||||
|
UInt32 headerSize;
|
||||||
|
|
||||||
if (_version == 1)
|
if (_version == 1)
|
||||||
{
|
{
|
||||||
// _mTime = Get32(buf + 0x14); // is unused im most images
|
// _mTime = Get32((const Byte *)(const void *)buf64 + 0x14); // is unused in most images
|
||||||
_size = Get64(buf + 0x18);
|
_clusterBits = ((const Byte *)(const void *)buf64)[0x20];
|
||||||
_clusterBits = buf[0x20];
|
_numMidBits = ((const Byte *)(const void *)buf64)[0x21];
|
||||||
_numMidBits = buf[0x21];
|
|
||||||
if (_clusterBits < 9 || _clusterBits > 30)
|
if (_clusterBits < 9 || _clusterBits > 30)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
if (_numMidBits < 1 || _numMidBits > 28)
|
if (_numMidBits < 1 || _numMidBits > 28)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
_cryptMethod = Get32(buf + 0x24);
|
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x24);
|
||||||
l1Offset = Get64(buf + 0x28);
|
const unsigned numBits2 = _clusterBits + _numMidBits;
|
||||||
if (l1Offset < 0x30)
|
|
||||||
return S_FALSE;
|
|
||||||
const unsigned numBits2 = (_clusterBits + _numMidBits);
|
|
||||||
const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
|
const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
|
||||||
if (l1Size64 > ((UInt32)1 << 31))
|
if (l1Size64 > ((UInt32)1 << 31))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
l1Size = (UInt32)l1Size64;
|
l1Size = (size_t)l1Size64;
|
||||||
|
headerSize = 0x30;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_clusterBits = Get32(buf + 0x14);
|
_clusterBits = Get32((const Byte *)(const void *)buf64 + 0x14);
|
||||||
if (_clusterBits < 9 || _clusterBits > 30)
|
if (_clusterBits < 9 || _clusterBits > 30)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
_numMidBits = _clusterBits - 3;
|
_numMidBits = _clusterBits - 3;
|
||||||
_size = Get64(buf + 0x18);
|
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x20);
|
||||||
_cryptMethod = Get32(buf + 0x20);
|
l1Size = Get32((const Byte *)(const void *)buf64 + 0x24);
|
||||||
l1Size = Get32(buf + 0x24);
|
headerSize = 0x48;
|
||||||
l1Offset = Get64(buf + 0x28); // must be aligned for cluster
|
if (_version >= 3)
|
||||||
|
{
|
||||||
|
_incompatFlags = Get64((const Byte *)(const void *)buf64 + 0x48);
|
||||||
|
// const UInt64 CompatFlags = Get64((const Byte *)(const void *)buf64 + 0x50);
|
||||||
|
// const UInt64 AutoClearFlags = Get64((const Byte *)(const void *)buf64 + 0x58);
|
||||||
|
// const UInt32 RefCountOrder = Get32((const Byte *)(const void *)buf64 + 0x60);
|
||||||
|
headerSize = 0x68;
|
||||||
|
const UInt32 headerSize2 = Get32((const Byte *)(const void *)buf64 + 0x64);
|
||||||
|
if (headerSize2 > (1u << 30))
|
||||||
|
return S_FALSE;
|
||||||
|
if (headerSize < headerSize2)
|
||||||
|
headerSize = headerSize2;
|
||||||
|
if (headerSize2 >= 0x68 + 1)
|
||||||
|
_compressionType = ((const Byte *)(const void *)buf64)[0x68];
|
||||||
|
}
|
||||||
|
|
||||||
const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster
|
const UInt64 refOffset = Get64((const Byte *)(const void *)buf64 + 0x30); // must be aligned for cluster
|
||||||
const UInt32 refClusters = Get32(buf + 0x38);
|
const UInt32 refClusters = Get32((const Byte *)(const void *)buf64 + 0x38);
|
||||||
|
// UInt32 numSnapshots = Get32((const Byte *)(const void *)buf64 + 0x3C);
|
||||||
// UInt32 numSnapshots = Get32(buf + 0x3C);
|
// UInt64 snapshotsOffset = Get64((const Byte *)(const void *)buf64 + 0x40); // must be aligned for cluster
|
||||||
// UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster
|
|
||||||
/*
|
/*
|
||||||
if (numSnapshots != 0)
|
if (numSnapshots)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
*/
|
*/
|
||||||
|
if (refClusters)
|
||||||
if (refClusters != 0)
|
|
||||||
{
|
{
|
||||||
const size_t numBytes = refClusters << _clusterBits;
|
if (refOffset > k_CompressedSize_MAX)
|
||||||
|
return S_FALSE;
|
||||||
|
const UInt64 numBytes = (UInt64)refClusters << _clusterBits;
|
||||||
|
const UInt64 end = refOffset + numBytes;
|
||||||
|
if (end > k_CompressedSize_MAX)
|
||||||
|
return S_FALSE;
|
||||||
/*
|
/*
|
||||||
CByteBuffer refs;
|
CByteBuffer refs;
|
||||||
refs.Alloc(numBytes);
|
refs.Alloc(numBytes);
|
||||||
RINOK(InStream_SeekSet(stream, refOffset))
|
RINOK(InStream_SeekSet(stream, refOffset))
|
||||||
RINOK(ReadStream_FALSE(stream, refs, numBytes));
|
RINOK(ReadStream_FALSE(stream, refs, numBytes));
|
||||||
*/
|
*/
|
||||||
const UInt64 end = refOffset + numBytes;
|
|
||||||
if (_phySize < end)
|
if (_phySize < end)
|
||||||
_phySize = end;
|
_phySize = end;
|
||||||
/*
|
/*
|
||||||
for (size_t i = 0; i < numBytes; i += 2)
|
for (size_t i = 0; i < numBytes; i += 2)
|
||||||
{
|
{
|
||||||
|
|
@ -436,48 +476,76 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_isArc = true;
|
const UInt64 l1Offset = Get64((const Byte *)(const void *)buf64 + 0x28); // must be aligned for cluster ?
|
||||||
|
if (l1Offset < headerSize || l1Offset > k_CompressedSize_MAX)
|
||||||
if (backOffset != 0)
|
|
||||||
{
|
|
||||||
_unsupported = true;
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
if (_phySize < headerSize)
|
||||||
|
_phySize = headerSize;
|
||||||
|
|
||||||
|
_isArc = true;
|
||||||
|
{
|
||||||
|
const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8);
|
||||||
|
// UInt32 backSize = Get32((const Byte *)(const void *)buf64 + 0x10);
|
||||||
|
if (backOffset)
|
||||||
|
{
|
||||||
|
_unsupported = true;
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt64 fileSize = 0;
|
||||||
|
RINOK(InStream_GetSize_SeekToBegin(stream, fileSize))
|
||||||
|
|
||||||
const size_t clusterSize = (size_t)1 << _clusterBits;
|
const size_t clusterSize = (size_t)1 << _clusterBits;
|
||||||
|
const size_t t1SizeBytes = (size_t)l1Size << 3;
|
||||||
CByteBuffer table;
|
|
||||||
{
|
{
|
||||||
const size_t t1SizeBytes = (size_t)l1Size << 3;
|
const UInt64 end = l1Offset + t1SizeBytes;
|
||||||
if ((t1SizeBytes >> 3) != l1Size)
|
if (end > k_CompressedSize_MAX)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
table.Alloc(t1SizeBytes);
|
// we need to use align end for empty qcow files
|
||||||
RINOK(InStream_SeekSet(stream, l1Offset))
|
// some files has no cluster alignment padding at the end
|
||||||
RINOK(ReadStream_FALSE(stream, table, t1SizeBytes))
|
// but has sector alignment
|
||||||
|
// end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
|
||||||
{
|
if (_phySize < end)
|
||||||
UInt64 end = l1Offset + t1SizeBytes;
|
|
||||||
// we need to uses align end for empty qcow files
|
|
||||||
end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
|
|
||||||
if (_phySize < end)
|
|
||||||
_phySize = end;
|
_phySize = end;
|
||||||
|
if (end > fileSize)
|
||||||
|
return S_FALSE;
|
||||||
|
if (_phySize < fileSize)
|
||||||
|
{
|
||||||
|
const UInt64 end2 = (end + 511) & ~(UInt64)511;
|
||||||
|
if (end2 == fileSize)
|
||||||
|
_phySize = end2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CObjArray<UInt64> table64(l1Size);
|
||||||
|
{
|
||||||
|
// if ((t1SizeBytes >> 3) != l1Size) return S_FALSE;
|
||||||
|
RINOK(InStream_SeekSet(stream, l1Offset))
|
||||||
|
RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes))
|
||||||
|
}
|
||||||
|
|
||||||
_compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);
|
_compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);
|
||||||
const UInt64 offsetMask = _compressedFlag - 1;
|
const UInt64 offsetMask = _compressedFlag - 1;
|
||||||
|
const size_t midSize = (size_t)1 << (_numMidBits + 3);
|
||||||
UInt32 numTables = 0;
|
size_t numTables = 0;
|
||||||
UInt32 i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < l1Size; i++)
|
for (i = 0; i < l1Size; i++)
|
||||||
{
|
{
|
||||||
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
|
const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
|
||||||
if (v != 0)
|
if (!v)
|
||||||
numTables++;
|
continue;
|
||||||
|
numTables++;
|
||||||
|
const UInt64 end = v + midSize;
|
||||||
|
if (end > k_CompressedSize_MAX)
|
||||||
|
return S_FALSE;
|
||||||
|
if (_phySize < end)
|
||||||
|
_phySize = end;
|
||||||
|
if (end > fileSize)
|
||||||
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numTables != 0)
|
if (numTables)
|
||||||
{
|
{
|
||||||
const size_t size = (size_t)numTables << (_numMidBits + 3);
|
const size_t size = (size_t)numTables << (_numMidBits + 3);
|
||||||
if (size >> (_numMidBits + 3) != numTables)
|
if (size >> (_numMidBits + 3) != numTables)
|
||||||
|
|
@ -485,48 +553,38 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||||
_table.Alloc(size);
|
_table.Alloc(size);
|
||||||
if (!_table.IsAllocated())
|
if (!_table.IsAllocated())
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
if (openCallback)
|
||||||
|
{
|
||||||
|
const UInt64 totalBytes = size;
|
||||||
|
RINOK(openCallback->SetTotal(NULL, &totalBytes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_dir.SetSize(l1Size);
|
_dir.SetSize((unsigned)l1Size);
|
||||||
|
|
||||||
UInt32 curTable = 0;
|
UInt32 curTable = 0;
|
||||||
|
|
||||||
if (openCallback)
|
|
||||||
{
|
|
||||||
const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3);
|
|
||||||
RINOK(openCallback->SetTotal(NULL, &totalBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < l1Size; i++)
|
for (i = 0; i < l1Size; i++)
|
||||||
{
|
{
|
||||||
Byte *buf2;
|
Byte *buf2;
|
||||||
const size_t midSize = (size_t)1 << (_numMidBits + 3);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
|
const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
{
|
{
|
||||||
_dir[i] = kEmptyDirItem;
|
_dir[i] = kEmptyDirItem;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dir[i] = curTable;
|
_dir[i] = curTable;
|
||||||
const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3));
|
const size_t tableOffset = (size_t)curTable << (_numMidBits + 3);
|
||||||
buf2 = (Byte *)_table + tableOffset;
|
buf2 = (Byte *)_table + tableOffset;
|
||||||
curTable++;
|
curTable++;
|
||||||
|
|
||||||
if (openCallback && (tableOffset & 0xFFFFF) == 0)
|
if (openCallback && (tableOffset & 0xFFFFF) == 0)
|
||||||
{
|
{
|
||||||
const UInt64 numBytes = tableOffset;
|
const UInt64 numBytes = tableOffset;
|
||||||
RINOK(openCallback->SetCompleted(NULL, &numBytes))
|
RINOK(openCallback->SetCompleted(NULL, &numBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
RINOK(InStream_SeekSet(stream, v))
|
RINOK(InStream_SeekSet(stream, v))
|
||||||
RINOK(ReadStream_FALSE(stream, buf2, midSize))
|
RINOK(ReadStream_FALSE(stream, buf2, midSize))
|
||||||
|
|
||||||
const UInt64 end = v + midSize;
|
|
||||||
if (_phySize < end)
|
|
||||||
_phySize = end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t k = 0; k < midSize; k += 8)
|
for (size_t k = 0; k < midSize; k += 8)
|
||||||
|
|
@ -537,33 +595,30 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||||
UInt64 offset = v & offsetMask;
|
UInt64 offset = v & offsetMask;
|
||||||
size_t dataSize = clusterSize;
|
size_t dataSize = clusterSize;
|
||||||
|
|
||||||
if ((v & _compressedFlag) != 0)
|
if (v & _compressedFlag)
|
||||||
{
|
{
|
||||||
if (_version <= 1)
|
if (_version <= 1)
|
||||||
{
|
{
|
||||||
unsigned numOffsetBits = (63 - _clusterBits);
|
const unsigned numOffsetBits = 63 - _clusterBits;
|
||||||
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
||||||
offset &= ((UInt64)1 << numOffsetBits) - 1;
|
offset &= ((UInt64)1 << numOffsetBits) - 1;
|
||||||
dataSize = 0;
|
dataSize = 0; // why ?
|
||||||
// offset >>= 9;
|
// offset &= ~(((UInt64)1 << 9) - 1);
|
||||||
// offset <<= 9;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned numOffsetBits = (62 - (_clusterBits - 8));
|
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
|
||||||
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
|
||||||
offset &= ((UInt64)1 << numOffsetBits) - 1;
|
offset &= ((UInt64)1 << numOffsetBits) - (1 << 9);
|
||||||
offset >>= 9;
|
|
||||||
offset <<= 9;
|
|
||||||
}
|
}
|
||||||
_needDeflate = true;
|
_needCompression = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UInt32 low = (UInt32)v & 511;
|
const UInt32 low = (UInt32)v & 511;
|
||||||
if (low != 0)
|
if (low)
|
||||||
{
|
{
|
||||||
// version 3 support zero clusters
|
// version_3 supports zero clusters
|
||||||
if (_version < 3 || low != 1)
|
if (_version < 3 || low != 1)
|
||||||
{
|
{
|
||||||
_unsupported = true;
|
_unsupported = true;
|
||||||
|
|
@ -574,17 +629,18 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
|
||||||
|
|
||||||
const UInt64 end = offset + dataSize;
|
const UInt64 end = offset + dataSize;
|
||||||
if (_phySize < end)
|
if (_phySize < end)
|
||||||
_phySize = end;
|
_phySize = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curTable != numTables)
|
if (curTable != numTables)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if (_cryptMethod != 0)
|
if (_cryptMethod)
|
||||||
_unsupported = true;
|
_unsupported = true;
|
||||||
|
if (_needCompression && _version <= 1) // that case was not implemented
|
||||||
if (_needDeflate && _version <= 1) // that case was not implemented
|
_unsupported = true;
|
||||||
|
if (_compressionType)
|
||||||
_unsupported = true;
|
_unsupported = true;
|
||||||
|
|
||||||
Stream = stream;
|
Stream = stream;
|
||||||
|
|
@ -596,16 +652,21 @@ Z7_COM7F_IMF(CHandler::Close())
|
||||||
{
|
{
|
||||||
_table.Free();
|
_table.Free();
|
||||||
_dir.Free();
|
_dir.Free();
|
||||||
|
// _cache.Free();
|
||||||
|
// _cacheCompressed.Free();
|
||||||
_phySize = 0;
|
_phySize = 0;
|
||||||
|
|
||||||
_cacheCluster = (UInt64)(Int64)-1;
|
_cacheCluster = (UInt64)(Int64)-1;
|
||||||
_comprPos = 0;
|
_comprPos = 0;
|
||||||
_comprSize = 0;
|
_comprSize = 0;
|
||||||
_needDeflate = false;
|
|
||||||
|
|
||||||
|
_needCompression = false;
|
||||||
_isArc = false;
|
_isArc = false;
|
||||||
_unsupported = false;
|
_unsupported = false;
|
||||||
|
|
||||||
|
_compressionType = 0;
|
||||||
|
_incompatFlags = 0;
|
||||||
|
|
||||||
// CHandlerImg:
|
// CHandlerImg:
|
||||||
Clear_HandlerImg_Vars();
|
Clear_HandlerImg_Vars();
|
||||||
Stream.Release();
|
Stream.Release();
|
||||||
|
|
@ -617,39 +678,20 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
|
||||||
{
|
{
|
||||||
COM_TRY_BEGIN
|
COM_TRY_BEGIN
|
||||||
*stream = NULL;
|
*stream = NULL;
|
||||||
|
if (_unsupported || !Stream)
|
||||||
if (_unsupported)
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
if (_needCompression)
|
||||||
if (_needDeflate)
|
|
||||||
{
|
{
|
||||||
if (_version <= 1)
|
if (_version <= 1 || _compressionType)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
_bufInStream.Create_if_Empty();
|
||||||
if (!_bufInStream)
|
_bufOutStream.Create_if_Empty();
|
||||||
{
|
_deflateDecoder.Create_if_Empty();
|
||||||
_bufInStreamSpec = new CBufInStream;
|
_deflateDecoder->Set_NeedFinishInput(true);
|
||||||
_bufInStream = _bufInStreamSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_bufOutStream)
|
|
||||||
{
|
|
||||||
_bufOutStreamSpec = new CBufPtrSeqOutStream();
|
|
||||||
_bufOutStream = _bufOutStreamSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_deflateDecoder)
|
|
||||||
{
|
|
||||||
_deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
|
|
||||||
_deflateDecoder = _deflateDecoderSpec;
|
|
||||||
_deflateDecoderSpec->Set_NeedFinishInput(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t clusterSize = (size_t)1 << _clusterBits;
|
const size_t clusterSize = (size_t)1 << _clusterBits;
|
||||||
_cache.AllocAtLeast(clusterSize);
|
_cache.AllocAtLeast(clusterSize);
|
||||||
_cacheCompressed.AllocAtLeast(clusterSize * 2);
|
_cacheCompressed.AllocAtLeast(clusterSize * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMyComPtr<ISequentialInStream> streamTemp = this;
|
CMyComPtr<ISequentialInStream> streamTemp = this;
|
||||||
RINOK(InitAndSeek())
|
RINOK(InitAndSeek())
|
||||||
*stream = streamTemp.Detach();
|
*stream = streamTemp.Detach();
|
||||||
|
|
|
||||||
|
|
@ -1456,7 +1456,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
|
||||||
}
|
}
|
||||||
if (arcInfo->Locator.Is_Recovery())
|
if (arcInfo->Locator.Is_Recovery())
|
||||||
{
|
{
|
||||||
s += "Recovery:";
|
s.Add_OptSpaced("Recovery:");
|
||||||
s.Add_UInt64(arcInfo->Locator.Recovery);
|
s.Add_UInt64(arcInfo->Locator.Recovery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1755,16 +1755,17 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
|
||||||
PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
|
PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
|
||||||
if (_hres != S_OK)
|
if (_hres != S_OK)
|
||||||
return _hres;
|
return _hres;
|
||||||
if (size == 0 || _cachedSize == 0)
|
if (size > _cachedSize)
|
||||||
|
size = _cachedSize;
|
||||||
|
// (size <= _cachedSize)
|
||||||
|
if (size == 0)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
RINOK(SeekPhy(_cachedPos))
|
RINOK(SeekPhy(_cachedPos))
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// (_phyPos == _cachedPos)
|
// (_phyPos == _cachedPos)
|
||||||
const size_t pos = (size_t)_cachedPos & kCacheMask;
|
const size_t pos = (size_t)_cachedPos & kCacheMask;
|
||||||
size_t cur = kCacheSize - pos;
|
const size_t cur = MyMin(kCacheSize - pos, size);
|
||||||
cur = MyMin(cur, _cachedSize);
|
|
||||||
cur = MyMin(cur, size);
|
|
||||||
_hres = SetRestriction_ForWrite(cur);
|
_hres = SetRestriction_ForWrite(cur);
|
||||||
RINOK(_hres)
|
RINOK(_hres)
|
||||||
PRF(printf("\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)cur));
|
PRF(printf("\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)cur));
|
||||||
|
|
@ -1776,7 +1777,7 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
|
||||||
_cachedPos += cur;
|
_cachedPos += cur;
|
||||||
_cachedSize -= cur;
|
_cachedSize -= cur;
|
||||||
size -= cur;
|
size -= cur;
|
||||||
if (size == 0 || _cachedSize == 0)
|
if (size == 0)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1964,7 +1965,11 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
|
||||||
// so we reduce cache
|
// so we reduce cache
|
||||||
_cachedSize = (size_t)offset;
|
_cachedSize = (size_t)offset;
|
||||||
if (_phySize <= newSize)
|
if (_phySize <= newSize)
|
||||||
return S_OK; // _phySize will be restored later after cache flush
|
{
|
||||||
|
// _phySize will be restored later after cache flush
|
||||||
|
_virtSize = newSize;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
// (_phySize > newSize)
|
// (_phySize > newSize)
|
||||||
// so we must reduce phyStream size to (newSize) or to (_cachedPos)
|
// so we must reduce phyStream size to (newSize) or to (_cachedPos)
|
||||||
// newPhySize = _cachedPos; // optional reduce to _cachedPos
|
// newPhySize = _cachedPos; // optional reduce to _cachedPos
|
||||||
|
|
|
||||||
|
|
@ -3713,7 +3713,7 @@ HRESULT Bench(
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool ramSize_Defined = NSystem::GetRamSize(ramSize);
|
const bool ramSize_Defined = NSystem::GetRamSize(ramSize);
|
||||||
|
|
||||||
UInt32 numThreadsSpecified = numCPUs;
|
UInt32 numThreadsSpecified = numCPUs;
|
||||||
bool needSetComplexity = false;
|
bool needSetComplexity = false;
|
||||||
|
|
@ -4002,16 +4002,29 @@ HRESULT Bench(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numThreadsSpecified >= 2)
|
|
||||||
if (printCallback || freqCallback)
|
if (printCallback || freqCallback)
|
||||||
|
for (unsigned test = 0; test < 3; test++)
|
||||||
{
|
{
|
||||||
|
if (numThreadsSpecified < 2)
|
||||||
|
{
|
||||||
|
// if (test == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (test == 2 && numThreadsSpecified <= numCPUs)
|
||||||
|
break;
|
||||||
if (printCallback)
|
if (printCallback)
|
||||||
printCallback->NewLine();
|
printCallback->NewLine();
|
||||||
|
|
||||||
/* it can show incorrect frequency for HT threads.
|
/* it can show incorrect frequency for HT threads. */
|
||||||
so we reduce freq test to (numCPUs / 2) */
|
|
||||||
|
|
||||||
UInt32 numThreads = (numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2 : numThreadsSpecified);
|
UInt32 numThreads = numThreadsSpecified;
|
||||||
|
if (test < 2)
|
||||||
|
{
|
||||||
|
if (numThreads >= numCPUs)
|
||||||
|
numThreads = numCPUs;
|
||||||
|
if (test == 0)
|
||||||
|
numThreads /= 2;
|
||||||
|
}
|
||||||
if (numThreads < 1)
|
if (numThreads < 1)
|
||||||
numThreads = 1;
|
numThreads = 1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
using namespace NWindows;
|
using namespace NWindows;
|
||||||
|
|
||||||
static const unsigned kNumWinAtrribFlags = 21;
|
static const unsigned kNumWinAtrribFlags = 30;
|
||||||
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
|
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FILE_ATTRIBUTE_
|
FILE_ATTRIBUTE_
|
||||||
|
|
@ -48,8 +48,9 @@ FILE_ATTRIBUTE_
|
||||||
18 RECALL_ON_OPEN or EA
|
18 RECALL_ON_OPEN or EA
|
||||||
19 PINNED
|
19 PINNED
|
||||||
20 UNPINNED
|
20 UNPINNED
|
||||||
21 STRICTLY_SEQUENTIAL
|
21 STRICTLY_SEQUENTIAL (10.0.16267)
|
||||||
22 RECALL_ON_DATA_ACCESS
|
22 RECALL_ON_DATA_ACCESS
|
||||||
|
29 STRICTLY_SEQUENTIAL (10.0.17134+) (SMR Blob)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -107,10 +108,10 @@ void ConvertWinAttribToString(char *s, UInt32 wa) throw()
|
||||||
|
|
||||||
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
|
for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
|
||||||
{
|
{
|
||||||
UInt32 flag = (1 << i);
|
const UInt32 flag = (UInt32)1 << i;
|
||||||
if ((wa & flag) != 0)
|
if (wa & flag)
|
||||||
{
|
{
|
||||||
char c = g_WinAttribChars[i];
|
const char c = g_WinAttribChars[i];
|
||||||
if (c != '.')
|
if (c != '.')
|
||||||
{
|
{
|
||||||
wa &= ~flag;
|
wa &= ~flag;
|
||||||
|
|
|
||||||
|
|
@ -1606,7 +1606,23 @@ HRESULT UpdateArchive(
|
||||||
|
|
||||||
if (!MyMoveFile(tempPath, us2fs(arcPath)))
|
if (!MyMoveFile(tempPath, us2fs(arcPath)))
|
||||||
{
|
{
|
||||||
errorInfo.SetFromLastError("cannot move the file", tempPath);
|
errorInfo.SystemError = ::GetLastError();
|
||||||
|
errorInfo.Message = "cannot move the file";
|
||||||
|
if (errorInfo.SystemError == ERROR_INVALID_PARAMETER)
|
||||||
|
{
|
||||||
|
NFind::CFileInfo fi;
|
||||||
|
if (fi.Find(tempPath) &&
|
||||||
|
fi.Size > (UInt32)(Int32)-1)
|
||||||
|
{
|
||||||
|
// bool isFsDetected = false;
|
||||||
|
// if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected)
|
||||||
|
{
|
||||||
|
errorInfo.Message.Add_LF();
|
||||||
|
errorInfo.Message += "Archive file size exceeds 4 GB";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errorInfo.FileNames.Add(tempPath);
|
||||||
errorInfo.FileNames.Add(us2fs(arcPath));
|
errorInfo.FileNames.Add(us2fs(arcPath));
|
||||||
return errorInfo.Get_HRESULT_Error();
|
return errorInfo.Get_HRESULT_Error();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -924,11 +924,11 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NumArcsWithError++;
|
// we don't update NumArcsWithError, if error is not related to archive data.
|
||||||
if (result == E_ABORT
|
if (result == E_ABORT
|
||||||
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
|
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL))
|
||||||
)
|
|
||||||
return result;
|
return result;
|
||||||
|
NumArcsWithError++;
|
||||||
|
|
||||||
if (_se)
|
if (_se)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,8 @@ bool FindExt(const char *p, const UString &name, CStringFinder &finder);
|
||||||
bool FindExt(const char *p, const UString &name, CStringFinder &finder)
|
bool FindExt(const char *p, const UString &name, CStringFinder &finder)
|
||||||
{
|
{
|
||||||
const int dotPos = name.ReverseFind_Dot();
|
const int dotPos = name.ReverseFind_Dot();
|
||||||
if (dotPos < 0 || dotPos == (int)name.Len() - 1)
|
int len = (int)name.Len() - (dotPos + 1);
|
||||||
|
if (len == 0 || len > 32 || dotPos < 0)
|
||||||
return false;
|
return false;
|
||||||
return finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1));
|
return finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,8 +387,8 @@ Z7_COM7F_IMF(CAltStreamsFolder::WasChanged(Int32 *wasChanged))
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
|
const DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
|
||||||
bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
|
const bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
|
||||||
if (wasChangedLoc)
|
if (wasChangedLoc)
|
||||||
{
|
{
|
||||||
_findChangeNotification.FindNext();
|
_findChangeNotification.FindNext();
|
||||||
|
|
@ -666,16 +666,10 @@ Z7_COM7F_IMF(CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID
|
||||||
Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
||||||
{
|
{
|
||||||
const CAltStream &ss = Streams[index];
|
const CAltStream &ss = Streams[index];
|
||||||
*iconIndex = 0;
|
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
int iconIndexTemp;
|
_pathPrefix + us2fs(ss.Name),
|
||||||
if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
|
FILE_ATTRIBUTE_ARCHIVE,
|
||||||
0 // fi.Attrib
|
iconIndex);
|
||||||
, iconIndexTemp) != 0)
|
|
||||||
{
|
|
||||||
*iconIndex = iconIndexTemp;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return GetLastError_noZero_HRESULT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -782,6 +782,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex)
|
||||||
if (useSrcPanel)
|
if (useSrcPanel)
|
||||||
{
|
{
|
||||||
CCopyToOptions options;
|
CCopyToOptions options;
|
||||||
|
// options.src_Is_IO_FS_Folder = useFullItemPaths;
|
||||||
options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
|
options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
|
||||||
options.moveMode = move;
|
options.moveMode = move;
|
||||||
options.includeAltStreams = true;
|
options.includeAltStreams = true;
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,8 @@ bool CBrowseDialog::OnInit()
|
||||||
_filterCombo.SetCurSel(FilterIndex);
|
_filterCombo.SetCurSel(FilterIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
|
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
|
||||||
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
|
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
|
||||||
|
|
||||||
_list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
|
_list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
|
||||||
_list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
|
_list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
|
||||||
|
|
@ -690,19 +690,21 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
if (isDrive)
|
if (isDrive)
|
||||||
{
|
{
|
||||||
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
|
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
|
||||||
item.iImage = 0;
|
fi.Name + FCHAR_PATH_SEPARATOR,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
|
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
|
||||||
if (item.iImage < 0)
|
if (item.iImage < 0)
|
||||||
item.iImage = 0;
|
item.iImage = 0;
|
||||||
_list.InsertItem(&item);
|
_list.InsertItem(&item);
|
||||||
wchar_t s[64];
|
wchar_t s[64];
|
||||||
{
|
{
|
||||||
s[0] = 0;
|
s[0] = 0;
|
||||||
ConvertUtcFileTimeToString(fi.MTime, s,
|
if (!FILETIME_IsZero(fi.MTime))
|
||||||
|
ConvertUtcFileTimeToString(fi.MTime, s,
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
kTimestampPrintLevel_MIN
|
kTimestampPrintLevel_MIN
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -356,8 +356,8 @@ bool CBrowseDialog2::OnInit()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
|
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
|
||||||
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
|
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
|
||||||
|
|
||||||
unsigned columnIndex = 0;
|
unsigned columnIndex = 0;
|
||||||
_list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
|
_list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
|
||||||
|
|
@ -1639,15 +1639,15 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
if (isDrive)
|
if (isDrive)
|
||||||
{
|
{
|
||||||
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
|
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
|
||||||
item.iImage = 0;
|
fi.Name + FCHAR_PATH_SEPARATOR,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
|
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
|
||||||
if (item.iImage < 0)
|
if (item.iImage < 0)
|
||||||
item.iImage = 0;
|
item.iImage = 0;
|
||||||
|
|
||||||
_list.InsertItem(&item);
|
_list.InsertItem(&item);
|
||||||
wchar_t s[64];
|
wchar_t s[64];
|
||||||
{
|
{
|
||||||
|
|
@ -1662,7 +1662,6 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
|
||||||
);
|
);
|
||||||
_list.SetSubItem(index, subItem++, s);
|
_list.SetSubItem(index, subItem++, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
s[0] = 0;
|
s[0] = 0;
|
||||||
Browse_ConvertSizeToString(bi, s);
|
Browse_ConvertSizeToString(bi, s);
|
||||||
|
|
|
||||||
|
|
@ -206,13 +206,15 @@ Z7_COM7F_IMF(CExtractCallbackImp::AskOverwrite(
|
||||||
{
|
{
|
||||||
COverwriteDialog dialog;
|
COverwriteDialog dialog;
|
||||||
|
|
||||||
dialog.OldFileInfo.SetTime(existTime);
|
dialog.OldFileInfo.SetTime2(existTime);
|
||||||
dialog.OldFileInfo.SetSize(existSize);
|
dialog.OldFileInfo.SetSize2(existSize);
|
||||||
dialog.OldFileInfo.Name = existName;
|
dialog.OldFileInfo.Path = existName;
|
||||||
|
dialog.OldFileInfo.Is_FileSystemFile = true;
|
||||||
|
|
||||||
dialog.NewFileInfo.SetTime(newTime);
|
dialog.NewFileInfo.SetTime2(newTime);
|
||||||
dialog.NewFileInfo.SetSize(newSize);
|
dialog.NewFileInfo.SetSize2(newSize);
|
||||||
dialog.NewFileInfo.Name = newName;
|
dialog.NewFileInfo.Path = newName;
|
||||||
|
dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder;
|
||||||
|
|
||||||
ProgressDialog->WaitCreating();
|
ProgressDialog->WaitCreating();
|
||||||
INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
|
INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,8 @@ public:
|
||||||
bool ProcessAltStreams;
|
bool ProcessAltStreams;
|
||||||
bool StreamMode;
|
bool StreamMode;
|
||||||
bool ThereAreMessageErrors;
|
bool ThereAreMessageErrors;
|
||||||
|
bool Src_Is_IO_FS_Folder;
|
||||||
|
|
||||||
#ifndef Z7_NO_CRYPTO
|
#ifndef Z7_NO_CRYPTO
|
||||||
bool PasswordIsDefined;
|
bool PasswordIsDefined;
|
||||||
bool PasswordWasAsked;
|
bool PasswordWasAsked;
|
||||||
|
|
@ -286,6 +288,8 @@ public:
|
||||||
, MultiArcMode(false)
|
, MultiArcMode(false)
|
||||||
, ProcessAltStreams(true)
|
, ProcessAltStreams(true)
|
||||||
, StreamMode(false)
|
, StreamMode(false)
|
||||||
|
, ThereAreMessageErrors(false)
|
||||||
|
, Src_Is_IO_FS_Folder(false)
|
||||||
#ifndef Z7_NO_CRYPTO
|
#ifndef Z7_NO_CRYPTO
|
||||||
, PasswordIsDefined(false)
|
, PasswordIsDefined(false)
|
||||||
, PasswordWasAsked(false)
|
, PasswordWasAsked(false)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ struct CPhysTempBuffer
|
||||||
~CPhysTempBuffer() { MidFree(buffer); }
|
~CPhysTempBuffer() { MidFree(buffer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize,
|
static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath,
|
||||||
|
bool writeToDisk, UInt64 fileSize,
|
||||||
UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
|
UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
|
||||||
{
|
{
|
||||||
NIO::CInFile inFile;
|
NIO::CInFile inFile;
|
||||||
|
|
@ -74,9 +75,11 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
|
||||||
|
|
||||||
for (UInt64 pos = 0; pos < fileSize;)
|
for (UInt64 pos = 0; pos < fileSize;)
|
||||||
{
|
{
|
||||||
UInt64 progressCur = progressStart + pos;
|
{
|
||||||
RINOK(progress->SetCompleted(&progressCur))
|
const UInt64 progressCur = progressStart + pos;
|
||||||
UInt64 rem = fileSize - pos;
|
RINOK(progress->SetCompleted(&progressCur))
|
||||||
|
}
|
||||||
|
const UInt64 rem = fileSize - pos;
|
||||||
UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
|
UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
|
||||||
UInt32 processedSize;
|
UInt32 processedSize;
|
||||||
if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
|
if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
|
||||||
|
|
@ -91,7 +94,6 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
|
||||||
if (curSize > bufferSize)
|
if (curSize > bufferSize)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
|
if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
|
||||||
return GetLastError_noZero_HRESULT();
|
return GetLastError_noZero_HRESULT();
|
||||||
if (curSize != processedSize)
|
if (curSize != processedSize)
|
||||||
|
|
@ -135,9 +137,7 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
|
||||||
FOR_VECTOR (i, driveStrings)
|
FOR_VECTOR (i, driveStrings)
|
||||||
{
|
{
|
||||||
CDriveInfo di;
|
CDriveInfo di;
|
||||||
|
|
||||||
const FString &driveName = driveStrings[i];
|
const FString &driveName = driveStrings[i];
|
||||||
|
|
||||||
di.FullSystemName = driveName;
|
di.FullSystemName = driveName;
|
||||||
if (!driveName.IsEmpty())
|
if (!driveName.IsEmpty())
|
||||||
di.Name.SetFrom(driveName, driveName.Len() - 1);
|
di.Name.SetFrom(driveName, driveName.Len() - 1);
|
||||||
|
|
@ -183,25 +183,24 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
|
||||||
{
|
{
|
||||||
FString name ("PhysicalDrive");
|
FString name ("PhysicalDrive");
|
||||||
name.Add_UInt32(n);
|
name.Add_UInt32(n);
|
||||||
|
|
||||||
FString fullPath (kVolPrefix);
|
FString fullPath (kVolPrefix);
|
||||||
fullPath += name;
|
fullPath += name;
|
||||||
|
|
||||||
CFileInfo fi;
|
CFileInfo fi;
|
||||||
if (!fi.Find(fullPath))
|
if (!fi.Find(fullPath))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CDriveInfo di;
|
CDriveInfo di;
|
||||||
di.Name = name;
|
di.Name = name;
|
||||||
di.FullSystemName = fullPath;
|
// if (_volumeMode == true) we use CDriveInfo::FullSystemName only in GetSystemIconIndex().
|
||||||
|
// And we need name without "\\\\.\\" prefix in GetSystemIconIndex().
|
||||||
|
// So we don't set di.FullSystemName = fullPath;
|
||||||
|
di.FullSystemName = name;
|
||||||
di.ClusterSize = 0;
|
di.ClusterSize = 0;
|
||||||
di.DriveSize = fi.Size;
|
di.DriveSize = fi.Size;
|
||||||
di.FreeSpace = 0;
|
di.FreeSpace = 0;
|
||||||
di.DriveType = 0;
|
di.DriveType = 0;
|
||||||
|
|
||||||
di.IsPhysicalDrive = true;
|
di.IsPhysicalDrive = true;
|
||||||
di.KnownSize = true;
|
di.KnownSize = true;
|
||||||
|
|
||||||
_drives.Add(di);
|
_drives.Add(di);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +216,7 @@ Z7_COM7F_IMF(CFSDrives::GetNumberOfItems(UInt32 *numItems))
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value))
|
Z7_COM7F_IMF(CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value))
|
||||||
{
|
{
|
||||||
if (itemIndex >= (UInt32)_drives.Size())
|
if (itemIndex >= _drives.Size())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
const CDriveInfo &di = _drives[itemIndex];
|
const CDriveInfo &di = _drives[itemIndex];
|
||||||
|
|
@ -268,7 +267,7 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
|
||||||
Z7_COM7F_IMF(CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder))
|
Z7_COM7F_IMF(CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder))
|
||||||
{
|
{
|
||||||
*resultFolder = NULL;
|
*resultFolder = NULL;
|
||||||
if (index >= (UInt32)_drives.Size())
|
if (index >= _drives.Size())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
const CDriveInfo &di = _drives[index];
|
const CDriveInfo &di = _drives[index];
|
||||||
/*
|
/*
|
||||||
|
|
@ -322,17 +321,14 @@ Z7_COM7F_IMF(CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value))
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
Z7_COM7F_IMF(CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
||||||
{
|
{
|
||||||
*iconIndex = 0;
|
*iconIndex = -1;
|
||||||
const CDriveInfo &di = _drives[index];
|
const CDriveInfo &di = _drives[index];
|
||||||
if (di.IsPhysicalDrive)
|
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
return S_OK;
|
di.FullSystemName,
|
||||||
int iconIndexTemp;
|
_volumeMode ?
|
||||||
if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0)
|
FILE_ATTRIBUTE_ARCHIVE:
|
||||||
{
|
FILE_ATTRIBUTE_DIRECTORY,
|
||||||
*iconIndex = iconIndexTemp;
|
iconIndex);
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return GetLastError_noZero_HRESULT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFSDrives::AddExt(FString &s, unsigned index) const
|
void CFSDrives::AddExt(FString &s, unsigned index) const
|
||||||
|
|
@ -393,10 +389,8 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||||
{
|
{
|
||||||
if (numItems == 0)
|
if (numItems == 0)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
if (moveMode)
|
if (moveMode)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
|
|
||||||
if (!_volumeMode)
|
if (!_volumeMode)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
|
|
||||||
|
|
@ -411,12 +405,12 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||||
RINOK(callback->SetTotal(totalSize))
|
RINOK(callback->SetTotal(totalSize))
|
||||||
RINOK(callback->SetNumFiles(numItems))
|
RINOK(callback->SetNumFiles(numItems))
|
||||||
|
|
||||||
FString destPath = us2fs(path);
|
const FString destPath = us2fs(path);
|
||||||
if (destPath.IsEmpty())
|
if (destPath.IsEmpty())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
bool isAltDest = NName::IsAltPathPrefix(destPath);
|
const bool isAltDest = NName::IsAltPathPrefix(destPath);
|
||||||
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
|
const bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
|
||||||
|
|
||||||
if (isDirectPath)
|
if (isDirectPath)
|
||||||
{
|
{
|
||||||
|
|
@ -428,7 +422,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||||
RINOK(callback->SetCompleted(&completedSize))
|
RINOK(callback->SetCompleted(&completedSize))
|
||||||
for (i = 0; i < numItems; i++)
|
for (i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
unsigned index = indices[i];
|
const unsigned index = indices[i];
|
||||||
const CDriveInfo &di = _drives[index];
|
const CDriveInfo &di = _drives[index];
|
||||||
FString destPath2 = destPath;
|
FString destPath2 = destPath;
|
||||||
|
|
||||||
|
|
@ -443,7 +437,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
|
||||||
destPath2 += destName;
|
destPath2 += destName;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString srcPath = di.GetDeviceFileIoName();
|
const FString srcPath = di.GetDeviceFileIoName();
|
||||||
|
|
||||||
UInt64 fileSize = 0;
|
UInt64 fileSize = 0;
|
||||||
if (GetFileSize(index, fileSize) != S_OK)
|
if (GetFileSize(index, fileSize) != S_OK)
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||||
{
|
{
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
/*
|
/*
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
{
|
{
|
||||||
CAltStream &ss = Streams[index - Files.Size()];
|
CAltStream &ss = Streams[index - Files.Size()];
|
||||||
CDirItem &fi = Files[ss.Parent];
|
CDirItem &fi = Files[ss.Parent];
|
||||||
|
|
@ -561,7 +561,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
||||||
case kpidComment: break;
|
case kpidComment: break;
|
||||||
default: index = ss.Parent;
|
default: index = ss.Parent;
|
||||||
}
|
}
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
{
|
{
|
||||||
prop.Detach(value);
|
prop.Detach(value);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
@ -716,8 +716,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI
|
||||||
/*
|
/*
|
||||||
const CAltStream *ss1 = NULL;
|
const CAltStream *ss1 = NULL;
|
||||||
const CAltStream *ss2 = NULL;
|
const CAltStream *ss2 = NULL;
|
||||||
if (index1 >= (UInt32)Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
|
if (index1 >= Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
|
||||||
if (index2 >= (UInt32)Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
|
if (index2 >= Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
|
||||||
*/
|
*/
|
||||||
CDirItem &fi1 = Files[index1];
|
CDirItem &fi1 = Files[index1];
|
||||||
CDirItem &fi2 = Files[index2];
|
CDirItem &fi2 = Files[index2];
|
||||||
|
|
@ -1034,7 +1034,7 @@ Z7_COM7F_IMF(CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgr
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress))
|
Z7_COM7F_IMF(CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress))
|
||||||
{
|
{
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
return S_OK;
|
return S_OK;
|
||||||
CDirItem &fi = Files[index];
|
CDirItem &fi = Files[index];
|
||||||
if (!fi.IsDir())
|
if (!fi.IsDir())
|
||||||
|
|
@ -1080,7 +1080,7 @@ Z7_COM7F_IMF(CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */))
|
Z7_COM7F_IMF(CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */))
|
||||||
{
|
{
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
const CDirItem &fi = Files[index];
|
const CDirItem &fi = Files[index];
|
||||||
// FString prefix;
|
// FString prefix;
|
||||||
|
|
@ -1103,9 +1103,9 @@ Z7_COM7F_IMF(CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress
|
||||||
UInt32 index = indices[i];
|
UInt32 index = indices[i];
|
||||||
bool result = true;
|
bool result = true;
|
||||||
/*
|
/*
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
{
|
{
|
||||||
const CAltStream &ss = Streams[index - (UInt32)Files.Size()];
|
const CAltStream &ss = Streams[index - Files.Size()];
|
||||||
if (prevDeletedFileIndex != ss.Parent)
|
if (prevDeletedFileIndex != ss.Parent)
|
||||||
{
|
{
|
||||||
const CDirItem &fi = Files[ss.Parent];
|
const CDirItem &fi = Files[ss.Parent];
|
||||||
|
|
@ -1134,7 +1134,7 @@ Z7_COM7F_IMF(CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress
|
||||||
Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID,
|
Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID,
|
||||||
const PROPVARIANT *value, IProgress * /* progress */))
|
const PROPVARIANT *value, IProgress * /* progress */))
|
||||||
{
|
{
|
||||||
if (index >= (UInt32)Files.Size())
|
if (index >= Files.Size())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
CDirItem &fi = Files[index];
|
CDirItem &fi = Files[index];
|
||||||
if (fi.Parent >= 0)
|
if (fi.Parent >= 0)
|
||||||
|
|
@ -1172,17 +1172,12 @@ Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID,
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
Z7_COM7F_IMF(CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
||||||
{
|
{
|
||||||
if (index >= (UInt32)Files.Size())
|
*iconIndex = -1;
|
||||||
|
if (index >= Files.Size())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
const CDirItem &fi = Files[index];
|
const CDirItem &fi = Files[index];
|
||||||
*iconIndex = 0;
|
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
int iconIndexTemp;
|
_path + GetRelPath(fi), fi.Attrib, iconIndex);
|
||||||
if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0)
|
|
||||||
{
|
|
||||||
*iconIndex = iconIndexTemp;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
return GetLastError_noZero_HRESULT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode))
|
Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode))
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ class CFSFolder;
|
||||||
|
|
||||||
struct CDirItem: public NWindows::NFile::NFind::CFileInfo
|
struct CDirItem: public NWindows::NFile::NFind::CFileInfo
|
||||||
{
|
{
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
UInt64 PackSize;
|
UInt64 PackSize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FS_SHOW_LINKS_INFO
|
#ifdef FS_SHOW_LINKS_INFO
|
||||||
FILETIME ChangeTime;
|
FILETIME ChangeTime;
|
||||||
UInt64 FileIndex;
|
UInt64 FileIndex;
|
||||||
UInt32 NumLinks;
|
UInt32 NumLinks;
|
||||||
|
|
@ -34,22 +34,21 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfo
|
||||||
bool FileInfo_WasRequested;
|
bool FileInfo_WasRequested;
|
||||||
bool ChangeTime_Defined;
|
bool ChangeTime_Defined;
|
||||||
bool ChangeTime_WasRequested;
|
bool ChangeTime_WasRequested;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
bool PackSize_Defined;
|
bool PackSize_Defined;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool FolderStat_Defined;
|
bool FolderStat_Defined;
|
||||||
|
int Parent;
|
||||||
|
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
CByteBuffer Reparse;
|
CByteBuffer Reparse;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UInt64 NumFolders;
|
UInt64 NumFolders;
|
||||||
UInt64 NumFiles;
|
UInt64 NumFiles;
|
||||||
|
|
||||||
int Parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -126,20 +125,18 @@ class CFSFolder Z7_final:
|
||||||
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
|
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
|
||||||
// Z7_IFACE_COM7_IMP(IFolderSetShowNtfsStreamsMode)
|
// Z7_IFACE_COM7_IMP(IFolderSetShowNtfsStreamsMode)
|
||||||
|
|
||||||
private:
|
bool _flatMode;
|
||||||
FString _path;
|
bool _commentsAreLoaded;
|
||||||
|
// bool _scanAltStreams;
|
||||||
|
|
||||||
|
FString _path;
|
||||||
CObjectVector<CDirItem> Files;
|
CObjectVector<CDirItem> Files;
|
||||||
FStringVector Folders;
|
FStringVector Folders;
|
||||||
// CObjectVector<CAltStream> Streams;
|
// CObjectVector<CAltStream> Streams;
|
||||||
// CMyComPtr<IFolderFolder> _parentFolder;
|
// CMyComPtr<IFolderFolder> _parentFolder;
|
||||||
|
|
||||||
bool _commentsAreLoaded;
|
|
||||||
CPairsStorage _comments;
|
CPairsStorage _comments;
|
||||||
|
|
||||||
// bool _scanAltStreams;
|
|
||||||
bool _flatMode;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
|
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -163,9 +160,11 @@ public:
|
||||||
HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
|
HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CFSFolder() : _flatMode(false)
|
CFSFolder():
|
||||||
|
_flatMode(false),
|
||||||
|
_commentsAreLoaded(false)
|
||||||
// , _scanAltStreams(false)
|
// , _scanAltStreams(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void GetFullPath(const CDirItem &item, FString &path) const
|
void GetFullPath(const CDirItem &item, FString &path) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -515,8 +515,22 @@ static HRESULT CopyFile_Ask(
|
||||||
RINOK(state.ProgressInfo.ProgressResult)
|
RINOK(state.ProgressInfo.ProgressResult)
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
|
const DWORD errorCode = GetLastError();
|
||||||
|
UString errorMessage = NError::MyFormatMessage(Return_LastError_or_FAIL());
|
||||||
|
if (errorCode == ERROR_INVALID_PARAMETER)
|
||||||
|
{
|
||||||
|
NFind::CFileInfo fi;
|
||||||
|
if (fi.Find(srcPath) &&
|
||||||
|
fi.Size > (UInt32)(Int32)-1)
|
||||||
|
{
|
||||||
|
// bool isFsDetected = false;
|
||||||
|
// if (NSystem::Is_File_LimitedBy_4GB(destPathNew, isFsDetected) || !isFsDetected)
|
||||||
|
errorMessage += " File size exceeds 4 GB";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
|
// GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
|
||||||
RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew))
|
RINOK(SendMessageError(state.Callback, errorMessage, destPathNew))
|
||||||
return E_ABORT;
|
return E_ABORT;
|
||||||
}
|
}
|
||||||
state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
|
state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
|
||||||
|
|
|
||||||
|
|
@ -254,28 +254,23 @@ Z7_COM7F_IMF(CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value))
|
||||||
|
|
||||||
Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
|
||||||
{
|
{
|
||||||
if (index >= (UInt32)_items.Size())
|
*iconIndex = -1;
|
||||||
|
if (index >= _items.Size())
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
*iconIndex = 0;
|
|
||||||
const CResourceW &resource = _items[index];
|
const CResourceW &resource = _items[index];
|
||||||
int iconIndexTemp;
|
|
||||||
if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
|
if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
|
||||||
resource.Usage == RESOURCEUSAGE_CONNECTABLE)
|
resource.Usage == RESOURCEUSAGE_CONNECTABLE)
|
||||||
{
|
{
|
||||||
if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp))
|
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
{
|
us2fs(resource.RemoteName), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
|
||||||
*iconIndex = iconIndexTemp;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp))
|
#if 0
|
||||||
{
|
return S_FALSE;
|
||||||
*iconIndex = iconIndexTemp;
|
#else
|
||||||
return S_OK;
|
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
}
|
FTEXT("__DIR__"), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
|
||||||
// *anIconIndex = GetRealIconIndex(0, L"\\\\HOME");
|
#endif
|
||||||
}
|
}
|
||||||
return GetLastError_noZero_HRESULT();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../Common/IntToString.h"
|
||||||
#include "../../../Common/StringConvert.h"
|
#include "../../../Common/StringConvert.h"
|
||||||
|
|
||||||
|
#include "../../../Windows/FileFind.h"
|
||||||
#include "../../../Windows/PropVariantConv.h"
|
#include "../../../Windows/PropVariantConv.h"
|
||||||
#include "../../../Windows/ResourceString.h"
|
#include "../../../Windows/ResourceString.h"
|
||||||
|
|
||||||
|
|
@ -29,12 +31,16 @@ static const UInt32 kLangIDs[] =
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const unsigned kCurrentFileNameSizeLimit = 82;
|
static const unsigned kCurrentFileNameSizeLimit = 72;
|
||||||
static const unsigned kCurrentFileNameSizeLimit2 = 30;
|
|
||||||
|
|
||||||
void COverwriteDialog::ReduceString(UString &s)
|
void COverwriteDialog::ReduceString(UString &s)
|
||||||
{
|
{
|
||||||
unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2;
|
const unsigned size =
|
||||||
|
#ifdef UNDER_CE
|
||||||
|
!_isBig ? 30 : // kCurrentFileNameSizeLimit2
|
||||||
|
#endif
|
||||||
|
kCurrentFileNameSizeLimit;
|
||||||
|
|
||||||
if (s.Len() > size)
|
if (s.Len() > size)
|
||||||
{
|
{
|
||||||
s.Delete(size / 2, s.Len() - size);
|
s.Delete(size / 2, s.Len() - size);
|
||||||
|
|
@ -42,66 +48,201 @@ void COverwriteDialog::ReduceString(UString &s)
|
||||||
}
|
}
|
||||||
if (!s.IsEmpty() && s.Back() == ' ')
|
if (!s.IsEmpty() && s.Back() == ' ')
|
||||||
{
|
{
|
||||||
// s += (wchar_t)(0x2423);
|
// s += (wchar_t)(0x2423); // visible space
|
||||||
s.InsertAtFront(L'\"');
|
s.InsertAtFront(L'\"');
|
||||||
s += L'\"';
|
s.Add_Char('\"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void COverwriteDialog::SetFileInfoControl(unsigned textID, unsigned iconID,
|
|
||||||
const NOverwriteDialog::CFileInfo &fileInfo)
|
void COverwriteDialog::SetItemIcon(unsigned iconID, HICON hIcon)
|
||||||
{
|
{
|
||||||
UString sizeString;
|
NControl::CStatic staticContol;
|
||||||
if (fileInfo.SizeIsDefined)
|
staticContol.Attach(GetItem(iconID));
|
||||||
sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
|
hIcon = staticContol.SetIcon(hIcon);
|
||||||
|
if (hIcon)
|
||||||
|
DestroyIcon(hIcon);
|
||||||
|
}
|
||||||
|
|
||||||
const UString &fileName = fileInfo.Name;
|
void AddSizeValue(UString &s, UInt64 value);
|
||||||
int slashPos = fileName.ReverseFind_PathSepar();
|
void AddSizeValue(UString &s, UInt64 value)
|
||||||
UString s1 = fileName.Left((unsigned)(slashPos + 1));
|
{
|
||||||
UString s2 = fileName.Ptr((unsigned)(slashPos + 1));
|
|
||||||
|
|
||||||
ReduceString(s1);
|
|
||||||
ReduceString(s2);
|
|
||||||
|
|
||||||
UString s = s1;
|
|
||||||
s.Add_LF();
|
|
||||||
s += s2;
|
|
||||||
s.Add_LF();
|
|
||||||
s += sizeString;
|
|
||||||
s.Add_LF();
|
|
||||||
|
|
||||||
if (fileInfo.TimeIsDefined)
|
|
||||||
{
|
{
|
||||||
AddLangString(s, IDS_PROP_MTIME);
|
wchar_t sz[32];
|
||||||
s += ": ";
|
ConvertUInt64ToString(value, sz);
|
||||||
char t[64];
|
s += MyFormatNew(IDS_FILE_SIZE, sz);
|
||||||
ConvertUtcFileTimeToString(fileInfo.Time, t);
|
|
||||||
s += t;
|
|
||||||
}
|
}
|
||||||
|
if (value >= (1 << 10))
|
||||||
NControl::CDialogChildControl control;
|
|
||||||
control.Init(*this, textID);
|
|
||||||
control.SetText(s);
|
|
||||||
|
|
||||||
SHFILEINFO shellFileInfo;
|
|
||||||
if (::SHGetFileInfo(
|
|
||||||
GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo,
|
|
||||||
sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON))
|
|
||||||
{
|
{
|
||||||
NControl::CStatic staticContol;
|
char c;
|
||||||
staticContol.Attach(GetItem(iconID));
|
if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }
|
||||||
staticContol.SetIcon(shellFileInfo.hIcon);
|
else if (value >= (10 << 20)) { value >>= 20; c = 'M'; }
|
||||||
|
else { value >>= 10; c = 'K'; }
|
||||||
|
s += " : ";
|
||||||
|
s.Add_UInt64(value);
|
||||||
|
s.Add_Space();
|
||||||
|
s.Add_Char(c);
|
||||||
|
s += "iB";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void COverwriteDialog::SetFileInfoControl(
|
||||||
|
const NOverwriteDialog::CFileInfo &fileInfo,
|
||||||
|
unsigned textID,
|
||||||
|
unsigned iconID,
|
||||||
|
unsigned iconID_2)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
const UString &path = fileInfo.Path;
|
||||||
|
const int slashPos = path.ReverseFind_PathSepar();
|
||||||
|
UString s = path.Left((unsigned)(slashPos + 1));
|
||||||
|
ReduceString(s);
|
||||||
|
s.Add_LF();
|
||||||
|
{
|
||||||
|
UString s2 = path.Ptr((unsigned)(slashPos + 1));
|
||||||
|
ReduceString(s2);
|
||||||
|
s += s2;
|
||||||
|
}
|
||||||
|
s.Add_LF();
|
||||||
|
if (fileInfo.Size_IsDefined)
|
||||||
|
AddSizeValue(s, fileInfo.Size);
|
||||||
|
s.Add_LF();
|
||||||
|
if (fileInfo.Time_IsDefined)
|
||||||
|
{
|
||||||
|
AddLangString(s, IDS_PROP_MTIME);
|
||||||
|
s += ": ";
|
||||||
|
char t[64];
|
||||||
|
ConvertUtcFileTimeToString(fileInfo.Time, t);
|
||||||
|
s += t;
|
||||||
|
}
|
||||||
|
SetItemText(textID, s);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
SHGetFileInfo():
|
||||||
|
DOCs: If uFlags does not contain SHGFI_EXETYPE or SHGFI_SYSICONINDEX,
|
||||||
|
the return value is nonzero if successful, or zero otherwise.
|
||||||
|
We don't use SHGFI_EXETYPE or SHGFI_SYSICONINDEX here.
|
||||||
|
win10: we call with SHGFI_ICON flag set.
|
||||||
|
it returns 0: if error : (shFileInfo::*) members are not set.
|
||||||
|
it returns non_0, if successful, and retrieve:
|
||||||
|
{ shFileInfo.hIcon != NULL : the handle to icon (must be destroyed by our code)
|
||||||
|
shFileInfo.iIcon is index of the icon image within the system image list.
|
||||||
|
}
|
||||||
|
Note:
|
||||||
|
If we send path to ".exe" file,
|
||||||
|
SHGFI_USEFILEATTRIBUTES flag is ignored, and it tries to open file.
|
||||||
|
and return icon from that exe file.
|
||||||
|
So we still need to reduce path, if want to get raw icon of exe file.
|
||||||
|
|
||||||
|
if (name.Len() >= MAX_PATH))
|
||||||
|
{
|
||||||
|
it can return:
|
||||||
|
return 0.
|
||||||
|
return 1 and:
|
||||||
|
{ shFileInfo.hIcon != NULL : is some default icon for file
|
||||||
|
shFileInfo.iIcon == 0
|
||||||
|
}
|
||||||
|
return results (0 or 1) can depend from:
|
||||||
|
- unicode/non-unicode
|
||||||
|
- (SHGFI_USEFILEATTRIBUTES) flag
|
||||||
|
- exact file extension (.exe).
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
int iconIndex = -1;
|
||||||
|
for (unsigned i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
CSysString name = GetSystemString(fileInfo.Path);
|
||||||
|
if (i != 0)
|
||||||
|
{
|
||||||
|
if (!fileInfo.Is_FileSystemFile)
|
||||||
|
break;
|
||||||
|
if (name.Len() < 4 ||
|
||||||
|
(!StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".exe") &&
|
||||||
|
!StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".ico")))
|
||||||
|
break;
|
||||||
|
// if path for ".exe" file is long, it returns default icon (shFileInfo.iIcon == 0).
|
||||||
|
// We don't want to show that default icon.
|
||||||
|
// But we will check for default icon later instead of MAX_PATH check here.
|
||||||
|
// if (name.Len() >= MAX_PATH) break; // optional
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we need only file extension with dot
|
||||||
|
const int separ = name.ReverseFind_PathSepar();
|
||||||
|
name.DeleteFrontal((unsigned)(separ + 1));
|
||||||
|
// if (name.Len() >= MAX_PATH)
|
||||||
|
{
|
||||||
|
const int dot = name.ReverseFind_Dot();
|
||||||
|
if (dot >= 0)
|
||||||
|
name.DeleteFrontal((unsigned)dot);
|
||||||
|
// else name.Empty(); to set default name below
|
||||||
|
}
|
||||||
|
// name.Empty(); // for debug
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.IsEmpty())
|
||||||
|
{
|
||||||
|
// If we send empty name, SHGetFileInfo() returns some strange icon.
|
||||||
|
// So we use common dummy name without extension,
|
||||||
|
// and SHGetFileInfo() will return default icon (iIcon == 0)
|
||||||
|
name = "__file__";
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD attrib = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
if (fileInfo.Is_FileSystemFile)
|
||||||
|
{
|
||||||
|
NFile::NFind::CFileInfo fi;
|
||||||
|
if (fi.Find(us2fs(fileInfo.Path)) && !fi.IsAltStream && !fi.IsDir())
|
||||||
|
attrib = fi.Attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHFILEINFO shFileInfo;
|
||||||
|
// ZeroMemory(&shFileInfo, sizeof(shFileInfo)); // optional
|
||||||
|
shFileInfo.hIcon = NULL; // optional
|
||||||
|
shFileInfo.iIcon = -1; // optional
|
||||||
|
// memset(&shFileInfo, 1, sizeof(shFileInfo)); // for debug
|
||||||
|
const DWORD_PTR res = ::SHGetFileInfo(name, attrib,
|
||||||
|
&shFileInfo, sizeof(shFileInfo),
|
||||||
|
SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SHELLICONSIZE |
|
||||||
|
// (i == 0 ? SHGFI_USEFILEATTRIBUTES : 0)
|
||||||
|
SHGFI_USEFILEATTRIBUTES
|
||||||
|
// we use SHGFI_USEFILEATTRIBUTES for second icon, because
|
||||||
|
// it still returns real icon from exe files
|
||||||
|
);
|
||||||
|
if (res && shFileInfo.hIcon)
|
||||||
|
{
|
||||||
|
// we don't show second icon, if icon index (iIcon) is same
|
||||||
|
// as first icon index of first shown icon (exe file without icon)
|
||||||
|
if ( shFileInfo.iIcon >= 0
|
||||||
|
&& shFileInfo.iIcon != iconIndex
|
||||||
|
&& (shFileInfo.iIcon != 0 || i == 0)) // we don't want default icon for second icon
|
||||||
|
{
|
||||||
|
iconIndex = shFileInfo.iIcon;
|
||||||
|
SetItemIcon(i == 0 ? iconID : iconID_2, shFileInfo.hIcon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DestroyIcon(shFileInfo.hIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool COverwriteDialog::OnInit()
|
bool COverwriteDialog::OnInit()
|
||||||
{
|
{
|
||||||
#ifdef Z7_LANG
|
#ifdef Z7_LANG
|
||||||
LangSetWindowText(*this, IDD_OVERWRITE);
|
LangSetWindowText(*this, IDD_OVERWRITE);
|
||||||
LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
|
LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
|
||||||
#endif
|
#endif
|
||||||
SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo);
|
SetFileInfoControl(OldFileInfo,
|
||||||
SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo);
|
IDT_OVERWRITE_OLD_FILE_SIZE_TIME,
|
||||||
|
IDI_OVERWRITE_OLD_FILE,
|
||||||
|
IDI_OVERWRITE_OLD_FILE_2);
|
||||||
|
SetFileInfoControl(NewFileInfo,
|
||||||
|
IDT_OVERWRITE_NEW_FILE_SIZE_TIME,
|
||||||
|
IDI_OVERWRITE_NEW_FILE,
|
||||||
|
IDI_OVERWRITE_NEW_FILE_2);
|
||||||
NormalizePosition();
|
NormalizePosition();
|
||||||
|
|
||||||
if (!ShowExtraButtons)
|
if (!ShowExtraButtons)
|
||||||
|
|
@ -122,6 +263,15 @@ bool COverwriteDialog::OnInit()
|
||||||
return CModalDialog::OnInit();
|
return CModalDialog::OnInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool COverwriteDialog::OnDestroy()
|
||||||
|
{
|
||||||
|
SetItemIcon(IDI_OVERWRITE_OLD_FILE, NULL);
|
||||||
|
SetItemIcon(IDI_OVERWRITE_OLD_FILE_2, NULL);
|
||||||
|
SetItemIcon(IDI_OVERWRITE_NEW_FILE, NULL);
|
||||||
|
SetItemIcon(IDI_OVERWRITE_NEW_FILE_2, NULL);
|
||||||
|
return false; // we return (false) to perform default dialog operation
|
||||||
|
}
|
||||||
|
|
||||||
bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
|
bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
|
||||||
{
|
{
|
||||||
switch (buttonID)
|
switch (buttonID)
|
||||||
|
|
|
||||||
|
|
@ -12,68 +12,78 @@ namespace NOverwriteDialog
|
||||||
{
|
{
|
||||||
struct CFileInfo
|
struct CFileInfo
|
||||||
{
|
{
|
||||||
bool SizeIsDefined;
|
bool Size_IsDefined;
|
||||||
bool TimeIsDefined;
|
bool Time_IsDefined;
|
||||||
|
bool Is_FileSystemFile;
|
||||||
UInt64 Size;
|
UInt64 Size;
|
||||||
FILETIME Time;
|
FILETIME Time;
|
||||||
UString Name;
|
UString Path;
|
||||||
|
|
||||||
void SetTime(const FILETIME *t)
|
void SetTime(const FILETIME &t)
|
||||||
|
{
|
||||||
|
Time = t;
|
||||||
|
Time_IsDefined = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTime2(const FILETIME *t)
|
||||||
{
|
{
|
||||||
if (!t)
|
if (!t)
|
||||||
TimeIsDefined = false;
|
Time_IsDefined = false;
|
||||||
else
|
else
|
||||||
{
|
SetTime(*t);
|
||||||
TimeIsDefined = true;
|
|
||||||
Time = *t;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSize(UInt64 size)
|
void SetSize(UInt64 size)
|
||||||
{
|
{
|
||||||
SizeIsDefined = true;
|
|
||||||
Size = size;
|
Size = size;
|
||||||
|
Size_IsDefined = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSize(const UInt64 *size)
|
void SetSize2(const UInt64 *size)
|
||||||
{
|
{
|
||||||
if (!size)
|
if (!size)
|
||||||
SizeIsDefined = false;
|
Size_IsDefined = false;
|
||||||
else
|
else
|
||||||
SetSize(*size);
|
SetSize(*size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFileInfo():
|
||||||
|
Size_IsDefined(false),
|
||||||
|
Time_IsDefined(false),
|
||||||
|
Is_FileSystemFile(false)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class COverwriteDialog: public NWindows::NControl::CModalDialog
|
class COverwriteDialog: public NWindows::NControl::CModalDialog
|
||||||
{
|
{
|
||||||
|
#ifdef UNDER_CE
|
||||||
bool _isBig;
|
bool _isBig;
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetFileInfoControl(unsigned textID, unsigned iconID, const NOverwriteDialog::CFileInfo &fileInfo);
|
void SetItemIcon(unsigned iconID, HICON hIcon);
|
||||||
|
void SetFileInfoControl(const NOverwriteDialog::CFileInfo &fileInfo, unsigned textID, unsigned iconID, unsigned iconID_2);
|
||||||
virtual bool OnInit() Z7_override;
|
virtual bool OnInit() Z7_override;
|
||||||
|
virtual bool OnDestroy() Z7_override;
|
||||||
virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
|
virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
|
||||||
void ReduceString(UString &s);
|
void ReduceString(UString &s);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool ShowExtraButtons;
|
bool ShowExtraButtons;
|
||||||
bool DefaultButton_is_NO;
|
bool DefaultButton_is_NO;
|
||||||
|
NOverwriteDialog::CFileInfo OldFileInfo;
|
||||||
|
NOverwriteDialog::CFileInfo NewFileInfo;
|
||||||
|
|
||||||
COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}
|
COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}
|
||||||
|
|
||||||
INT_PTR Create(HWND parent = NULL)
|
INT_PTR Create(HWND parent = NULL)
|
||||||
{
|
{
|
||||||
|
#ifdef UNDER_CE
|
||||||
BIG_DIALOG_SIZE(280, 200);
|
BIG_DIALOG_SIZE(280, 200);
|
||||||
#ifdef UNDER_CE
|
|
||||||
_isBig = isBig;
|
_isBig = isBig;
|
||||||
#else
|
#endif
|
||||||
_isBig = true;
|
|
||||||
#endif
|
|
||||||
return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
|
return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
NOverwriteDialog::CFileInfo OldFileInfo;
|
|
||||||
NOverwriteDialog::CFileInfo NewFileInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "OverwriteDialogRes.h"
|
#include "OverwriteDialogRes.h"
|
||||||
#include "../../GuiCommon.rc"
|
#include "../../GuiCommon.rc"
|
||||||
|
|
||||||
#define xc 280
|
#define xc 340
|
||||||
#define yc 200
|
#define yc 200
|
||||||
|
|
||||||
#undef iconSize
|
#undef iconSize
|
||||||
|
|
@ -25,11 +25,13 @@ BEGIN
|
||||||
LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8
|
LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8
|
||||||
|
|
||||||
ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize
|
ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize
|
||||||
|
ICON "", IDI_OVERWRITE_OLD_FILE_2, m, 44 + iconSize, iconSize, iconSize
|
||||||
LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX
|
LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX
|
||||||
|
|
||||||
LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8
|
LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8
|
||||||
|
|
||||||
ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize
|
ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize
|
||||||
|
ICON "", IDI_OVERWRITE_NEW_FILE_2, m, 114 + iconSize, iconSize, iconSize
|
||||||
LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX
|
LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX
|
||||||
|
|
||||||
PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
|
PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,9 @@
|
||||||
#define IDB_NO_TO_ALL 441
|
#define IDB_NO_TO_ALL 441
|
||||||
|
|
||||||
#define IDI_OVERWRITE_OLD_FILE 100
|
#define IDI_OVERWRITE_OLD_FILE 100
|
||||||
#define IDI_OVERWRITE_NEW_FILE 101
|
#define IDI_OVERWRITE_OLD_FILE_2 101
|
||||||
|
|
||||||
#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102
|
#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102
|
||||||
#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103
|
|
||||||
|
#define IDI_OVERWRITE_NEW_FILE 110
|
||||||
|
#define IDI_OVERWRITE_NEW_FILE_2 111
|
||||||
|
#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 112
|
||||||
|
|
|
||||||
|
|
@ -420,8 +420,8 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
|
||||||
_listView._panel = this;
|
_listView._panel = this;
|
||||||
_listView.SetWindowProc();
|
_listView.SetWindowProc();
|
||||||
|
|
||||||
_listView.SetImageList(GetSysImageList(true), LVSIL_SMALL);
|
_listView.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
|
||||||
_listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
|
_listView.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
|
||||||
|
|
||||||
// _exStyle |= LVS_EX_HEADERDRAGDROP;
|
// _exStyle |= LVS_EX_HEADERDRAGDROP;
|
||||||
// DWORD extendedStyle = _listView.GetExtendedListViewStyle();
|
// DWORD extendedStyle = _listView.GetExtendedListViewStyle();
|
||||||
|
|
@ -506,17 +506,15 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
|
||||||
#endif
|
#endif
|
||||||
, NULL,
|
, NULL,
|
||||||
WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
|
WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
|
||||||
0, 0, 100, 520,
|
0, 0, 100, 620,
|
||||||
(_headerReBar ? _headerToolBar : (HWND)*this),
|
(_headerReBar ? _headerToolBar : (HWND)*this),
|
||||||
(HMENU)(UINT_PTR)(_comboBoxID),
|
(HMENU)(UINT_PTR)(_comboBoxID),
|
||||||
g_hInstance, NULL);
|
g_hInstance, NULL);
|
||||||
#ifndef UNDER_CE
|
|
||||||
|
#ifndef UNDER_CE
|
||||||
_headerComboBox.SetUnicodeFormat(true);
|
_headerComboBox.SetUnicodeFormat(true);
|
||||||
|
_headerComboBox.SetImageList(Shell_Get_SysImageList_smallIcons(true));
|
||||||
_headerComboBox.SetImageList(GetSysImageList(true));
|
|
||||||
|
|
||||||
_headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
|
_headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
_headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
|
_headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
|
||||||
_headerComboBox._panel = this;
|
_headerComboBox._panel = this;
|
||||||
|
|
@ -525,9 +523,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
|
||||||
LONG_PTR(ComboBoxSubclassProc));
|
LONG_PTR(ComboBoxSubclassProc));
|
||||||
*/
|
*/
|
||||||
_comboBoxEdit.Attach(_headerComboBox.GetEditControl());
|
_comboBoxEdit.Attach(_headerComboBox.GetEditControl());
|
||||||
|
|
||||||
// _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
|
// _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
|
||||||
|
|
||||||
_comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
|
_comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
|
||||||
_comboBoxEdit._panel = this;
|
_comboBoxEdit._panel = this;
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
|
|
@ -538,8 +534,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
|
||||||
#endif
|
#endif
|
||||||
_comboBoxEdit._origWindowProc =
|
_comboBoxEdit._origWindowProc =
|
||||||
(WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
|
(WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
|
||||||
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
if (_headerReBar)
|
if (_headerReBar)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -147,11 +147,11 @@ public:
|
||||||
struct CTempFileInfo
|
struct CTempFileInfo
|
||||||
{
|
{
|
||||||
UInt32 FileIndex; // index of file in folder
|
UInt32 FileIndex; // index of file in folder
|
||||||
|
bool NeedDelete;
|
||||||
UString RelPath; // Relative path of file from Folder
|
UString RelPath; // Relative path of file from Folder
|
||||||
FString FolderPath;
|
FString FolderPath;
|
||||||
FString FilePath;
|
FString FilePath;
|
||||||
NWindows::NFile::NFind::CFileInfo FileInfo;
|
NWindows::NFile::NFind::CFileInfo FileInfo;
|
||||||
bool NeedDelete;
|
|
||||||
|
|
||||||
CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {}
|
CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {}
|
||||||
void DeleteDirAndFile() const
|
void DeleteDirAndFile() const
|
||||||
|
|
@ -171,15 +171,15 @@ struct CTempFileInfo
|
||||||
|
|
||||||
struct CFolderLink: public CTempFileInfo
|
struct CFolderLink: public CTempFileInfo
|
||||||
{
|
{
|
||||||
|
bool IsVirtual;
|
||||||
|
bool UsePassword;
|
||||||
NWindows::NDLL::CLibrary Library;
|
NWindows::NDLL::CLibrary Library;
|
||||||
CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
|
CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
|
||||||
UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
|
UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
|
||||||
bool UsePassword;
|
|
||||||
UString Password;
|
UString Password;
|
||||||
bool IsVirtual;
|
|
||||||
|
|
||||||
UString VirtualPath; // without tail slash
|
UString VirtualPath; // without tail slash
|
||||||
CFolderLink(): UsePassword(false), IsVirtual(false) {}
|
CFolderLink(): IsVirtual(false), UsePassword(false) {}
|
||||||
|
|
||||||
bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
|
bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
|
||||||
{
|
{
|
||||||
|
|
@ -310,7 +310,7 @@ struct COpenResult
|
||||||
|
|
||||||
class CPanel Z7_final: public NWindows::NControl::CWindow2
|
class CPanel Z7_final: public NWindows::NControl::CWindow2
|
||||||
{
|
{
|
||||||
CExtToIconMap _extToIconMap;
|
// CExtToIconMap _extToIconMap;
|
||||||
UINT _baseID;
|
UINT _baseID;
|
||||||
unsigned _comboBoxID;
|
unsigned _comboBoxID;
|
||||||
UINT _statusBarID;
|
UINT _statusBarID;
|
||||||
|
|
@ -324,7 +324,7 @@ class CPanel Z7_final: public NWindows::NControl::CWindow2
|
||||||
virtual void OnDestroy() Z7_override;
|
virtual void OnDestroy() Z7_override;
|
||||||
virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result) Z7_override;
|
virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result) Z7_override;
|
||||||
|
|
||||||
void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList);
|
void AddComboBoxItem(const UString &name, int iconIndex, unsigned indent, bool addToList);
|
||||||
|
|
||||||
bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);
|
bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);
|
||||||
|
|
||||||
|
|
@ -355,7 +355,7 @@ public:
|
||||||
HWND _mainWindow;
|
HWND _mainWindow;
|
||||||
CPanelCallback *_panelCallback;
|
CPanelCallback *_panelCallback;
|
||||||
|
|
||||||
void SysIconsWereChanged() { _extToIconMap.Clear(); }
|
// void SysIconsWereChanged() { _extToIconMap.Clear(); }
|
||||||
|
|
||||||
void DeleteItems(bool toRecycleBin);
|
void DeleteItems(bool toRecycleBin);
|
||||||
void CreateFolder();
|
void CreateFolder();
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,9 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options,
|
||||||
|
|
||||||
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
|
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
|
||||||
extracter.ExtractCallback = extracter.ExtractCallbackSpec;
|
extracter.ExtractCallback = extracter.ExtractCallbackSpec;
|
||||||
|
extracter.ExtractCallbackSpec->Src_Is_IO_FS_Folder =
|
||||||
|
IsFSFolder() || IsAltStreamsFolder();
|
||||||
|
// options.src_Is_IO_FS_Folder;
|
||||||
extracter.options = &options;
|
extracter.options = &options;
|
||||||
extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
|
extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
|
||||||
extracter.CompressingMode = false;
|
extracter.CompressingMode = false;
|
||||||
|
|
|
||||||
|
|
@ -368,14 +368,41 @@ void CPanel::LoadFullPath()
|
||||||
_currentFolderPrefix += GetFolderPath(_folder);
|
_currentFolderPrefix += GetFolderPath(_folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetRealIconIndex(CFSTR path, DWORD attributes)
|
|
||||||
|
|
||||||
|
static int GetRealIconIndex_for_DirPath(CFSTR path, DWORD attrib)
|
||||||
{
|
{
|
||||||
|
attrib |= FILE_ATTRIBUTE_DIRECTORY; // optional
|
||||||
int index = -1;
|
int index = -1;
|
||||||
if (GetRealIconIndex(path, attributes, index) != 0)
|
if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(path, attrib, index))
|
||||||
return index;
|
if (index >= 0)
|
||||||
return -1;
|
return index;
|
||||||
|
return g_Ext_to_Icon_Map.GetIconIndex_DIR(attrib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern UString RootFolder_GetName_Computer(int &iconIndex);
|
||||||
|
extern UString RootFolder_GetName_Network(int &iconIndex);
|
||||||
|
extern UString RootFolder_GetName_Documents(int &iconIndex);
|
||||||
|
|
||||||
|
|
||||||
|
static int Find_FileExtension_DotPos_in_path(const wchar_t *path)
|
||||||
|
{
|
||||||
|
int dotPos = -1;
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0;; i++)
|
||||||
|
{
|
||||||
|
const wchar_t c = path[i];
|
||||||
|
if (c == 0)
|
||||||
|
return dotPos;
|
||||||
|
if (c == '.')
|
||||||
|
dotPos = (int)i;
|
||||||
|
else if (IS_PATH_SEPAR(c) || c == ':')
|
||||||
|
dotPos = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CPanel::LoadFullPathAndShow()
|
void CPanel::LoadFullPathAndShow()
|
||||||
{
|
{
|
||||||
LoadFullPath();
|
LoadFullPath();
|
||||||
|
|
@ -387,30 +414,97 @@ void CPanel::LoadFullPathAndShow()
|
||||||
|
|
||||||
COMBOBOXEXITEM item;
|
COMBOBOXEXITEM item;
|
||||||
item.mask = 0;
|
item.mask = 0;
|
||||||
|
item.iImage = -1;
|
||||||
|
|
||||||
UString path = _currentFolderPrefix;
|
UString path = _currentFolderPrefix;
|
||||||
if (path.Len() >
|
// path = "\\\\.\\PhysicalDrive1\\"; // for debug
|
||||||
#ifdef _WIN32
|
// path = "\\\\.\\y:\\"; // for debug
|
||||||
3
|
if (!path.IsEmpty())
|
||||||
#else
|
|
||||||
1
|
|
||||||
#endif
|
|
||||||
&& IS_PATH_SEPAR(path.Back()))
|
|
||||||
path.DeleteBack();
|
|
||||||
|
|
||||||
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
|
|
||||||
|
|
||||||
// GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path
|
|
||||||
if (path.IsPrefixedBy(L"\\\\.\\"))
|
|
||||||
path = "_TestFolder_";
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
CFileInfo fi;
|
const unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
|
||||||
if (fi.Find(us2fs(path)))
|
if (rootPrefixSize == 0 && path[0] != '\\')
|
||||||
attrib = fi.Attrib;
|
{
|
||||||
}
|
int iconIndex = -1;
|
||||||
item.iImage = GetRealIconIndex(us2fs(path), attrib);
|
UString name_Computer = RootFolder_GetName_Computer(iconIndex);
|
||||||
|
name_Computer.Add_PathSepar();
|
||||||
|
if (path == name_Computer
|
||||||
|
|| path == L"\\\\?\\")
|
||||||
|
item.iImage = iconIndex;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UString name = RootFolder_GetName_Network(iconIndex);
|
||||||
|
name.Add_PathSepar();
|
||||||
|
if (path == name)
|
||||||
|
item.iImage = iconIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.iImage < 0)
|
||||||
|
{
|
||||||
|
if (rootPrefixSize == 0 || rootPrefixSize == path.Len())
|
||||||
|
{
|
||||||
|
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
CFileInfo info;
|
||||||
|
if (info.Find(us2fs(path)))
|
||||||
|
attrib = info.Attrib;
|
||||||
|
NName::If_IsSuperPath_RemoveSuperPrefix(path);
|
||||||
|
item.iImage = GetRealIconIndex_for_DirPath(us2fs(path), attrib);
|
||||||
|
}
|
||||||
|
else if (rootPrefixSize == NName::kDevicePathPrefixSize
|
||||||
|
&& NName::IsDevicePath(us2fs(path.Left(path.Len() - 1))))
|
||||||
|
{
|
||||||
|
if (path.IsPrefixedBy_Ascii_NoCase("\\\\.\\"))
|
||||||
|
path.DeleteFrontal(4);
|
||||||
|
if (path.Len() > 3) // is not "c:\\"
|
||||||
|
{
|
||||||
|
// PhysicalDrive
|
||||||
|
if (path.Back() == '\\')
|
||||||
|
path.DeleteBack();
|
||||||
|
}
|
||||||
|
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), FILE_ATTRIBUTE_ARCHIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (path.Back() == '\\')
|
||||||
|
path.DeleteBack();
|
||||||
|
bool need_Fs_Check = true;
|
||||||
|
bool is_File = false;
|
||||||
|
if (!_parentFolders.IsEmpty())
|
||||||
|
{
|
||||||
|
const CFolderLink &link = _parentFolders.Back();
|
||||||
|
if (link.VirtualPath == path)
|
||||||
|
{
|
||||||
|
is_File = true;
|
||||||
|
if (_parentFolders.Size() != 1)
|
||||||
|
need_Fs_Check = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
need_Fs_Check = false;
|
||||||
|
}
|
||||||
|
if (need_Fs_Check)
|
||||||
|
{
|
||||||
|
CFileInfo info;
|
||||||
|
const bool finded = info.Find(us2fs(path));
|
||||||
|
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
if (finded)
|
||||||
|
attrib = info.Attrib;
|
||||||
|
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), attrib);
|
||||||
|
}
|
||||||
|
if (item.iImage <= 0 && is_File)
|
||||||
|
{
|
||||||
|
int dotPos = Find_FileExtension_DotPos_in_path(path);
|
||||||
|
if (dotPos < 0)
|
||||||
|
dotPos = (int)path.Len();
|
||||||
|
item.iImage = g_Ext_to_Icon_Map.GetIconIndex(FILE_ATTRIBUTE_ARCHIVE, path.Ptr(dotPos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.iImage < 0)
|
||||||
|
item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
|
||||||
|
// if (item.iImage < 0) item.iImage = 0;
|
||||||
|
// item.iImage = -1; // for debug
|
||||||
if (item.iImage >= 0)
|
if (item.iImage >= 0)
|
||||||
{
|
{
|
||||||
item.iSelectedImage = item.iImage;
|
item.iSelectedImage = item.iImage;
|
||||||
|
|
@ -495,13 +589,13 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList)
|
void CPanel::AddComboBoxItem(const UString &name, int iconIndex, unsigned indent, bool addToList)
|
||||||
{
|
{
|
||||||
#ifdef UNDER_CE
|
#ifdef UNDER_CE
|
||||||
|
|
||||||
UString s;
|
UString s;
|
||||||
iconIndex = iconIndex;
|
iconIndex = iconIndex;
|
||||||
for (int i = 0; i < indent; i++)
|
for (unsigned i = 0; i < indent; i++)
|
||||||
s += " ";
|
s += " ";
|
||||||
_headerComboBox.AddString(s + name);
|
_headerComboBox.AddString(s + name);
|
||||||
|
|
||||||
|
|
@ -509,23 +603,26 @@ void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, boo
|
||||||
|
|
||||||
COMBOBOXEXITEMW item;
|
COMBOBOXEXITEMW item;
|
||||||
item.mask = CBEIF_TEXT | CBEIF_INDENT;
|
item.mask = CBEIF_TEXT | CBEIF_INDENT;
|
||||||
|
if (iconIndex < 0)
|
||||||
|
iconIndex = g_Ext_to_Icon_Map.GetIconIndex_DIR();
|
||||||
item.iSelectedImage = item.iImage = iconIndex;
|
item.iSelectedImage = item.iImage = iconIndex;
|
||||||
if (iconIndex >= 0)
|
if (iconIndex >= 0)
|
||||||
item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
|
item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
|
||||||
item.iItem = -1;
|
item.iItem = -1;
|
||||||
item.iIndent = indent;
|
item.iIndent = (int)indent;
|
||||||
item.pszText = name.Ptr_non_const();
|
item.pszText = name.Ptr_non_const();
|
||||||
_headerComboBox.InsertItem(&item);
|
_headerComboBox.InsertItem(&item);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (addToList)
|
if (addToList)
|
||||||
ComboBoxPaths.Add(name);
|
{
|
||||||
|
UString s = name;
|
||||||
|
s.Add_PathSepar();
|
||||||
|
ComboBoxPaths.Add(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern UString RootFolder_GetName_Computer(int &iconIndex);
|
|
||||||
extern UString RootFolder_GetName_Network(int &iconIndex);
|
|
||||||
extern UString RootFolder_GetName_Documents(int &iconIndex);
|
|
||||||
|
|
||||||
bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
|
bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
|
||||||
{
|
{
|
||||||
|
|
@ -537,56 +634,168 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
|
||||||
ComboBoxPaths.Clear();
|
ComboBoxPaths.Clear();
|
||||||
_headerComboBox.ResetContent();
|
_headerComboBox.ResetContent();
|
||||||
|
|
||||||
unsigned i;
|
UString sumPath;
|
||||||
UStringVector pathParts;
|
UStringVector pathParts;
|
||||||
|
unsigned indent = 0;
|
||||||
SplitPathToParts(_currentFolderPrefix, pathParts);
|
|
||||||
UString sumPass;
|
|
||||||
if (!pathParts.IsEmpty())
|
|
||||||
pathParts.DeleteBack();
|
|
||||||
for (i = 0; i < pathParts.Size(); i++)
|
|
||||||
{
|
{
|
||||||
const UString name = pathParts[i];
|
UString path = _currentFolderPrefix;
|
||||||
sumPass += name;
|
// path = L"\\\\.\\y:\\"; // for debug
|
||||||
sumPass.Add_PathSepar();
|
UString prefix0;
|
||||||
CFileInfo info;
|
if (path.IsPrefixedBy_Ascii_NoCase("\\\\"))
|
||||||
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
|
{
|
||||||
if (info.Find(us2fs(sumPass)))
|
const int separ = FindCharPosInString(path.Ptr(2), '\\');
|
||||||
attrib = info.Attrib;
|
if (separ > 0
|
||||||
AddComboBoxItem(
|
&& (separ > 1 || path[2] != '.')) // "\\\\.\\" will be processed later
|
||||||
name.IsEmpty() ? L"\\" : name,
|
{
|
||||||
GetRealIconIndex(us2fs(sumPass), attrib),
|
const UString s = path.Left(2 + separ);
|
||||||
(int)i, // iIndent
|
prefix0 = s;
|
||||||
|
prefix0.Add_PathSepar();
|
||||||
|
AddComboBoxItem(s,
|
||||||
|
GetRealIconIndex_for_DirPath(us2fs(prefix0), FILE_ATTRIBUTE_DIRECTORY),
|
||||||
|
indent++,
|
||||||
|
false); // addToList
|
||||||
|
ComboBoxPaths.Add(prefix0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
|
||||||
|
|
||||||
|
sumPath = path;
|
||||||
|
|
||||||
|
if (rootPrefixSize <= prefix0.Len())
|
||||||
|
{
|
||||||
|
rootPrefixSize = prefix0.Len();
|
||||||
|
sumPath.DeleteFrom(rootPrefixSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// rootPrefixSize > prefix0.Len()
|
||||||
|
sumPath.DeleteFrom(rootPrefixSize);
|
||||||
|
|
||||||
|
CFileInfo info;
|
||||||
|
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
if (info.Find(us2fs(sumPath)) && info.IsDir())
|
||||||
|
attrib = info.Attrib;
|
||||||
|
UString s = sumPath.Ptr(prefix0.Len());
|
||||||
|
if (!s.IsEmpty())
|
||||||
|
{
|
||||||
|
const wchar_t c = s.Back();
|
||||||
|
if (IS_PATH_SEPAR(c))
|
||||||
|
s.DeleteBack();
|
||||||
|
}
|
||||||
|
UString path_for_icon = sumPath;
|
||||||
|
NName::If_IsSuperPath_RemoveSuperPrefix(path_for_icon);
|
||||||
|
|
||||||
|
AddComboBoxItem(s,
|
||||||
|
GetRealIconIndex_for_DirPath(us2fs(path_for_icon), attrib),
|
||||||
|
indent++,
|
||||||
|
false); // addToList
|
||||||
|
ComboBoxPaths.Add(sumPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.DeleteFrontal(rootPrefixSize);
|
||||||
|
SplitPathToParts(path, pathParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's expected that pathParts.Back() is empty, because _currentFolderPrefix has PathSeparator.
|
||||||
|
unsigned next_Arc_index = 0;
|
||||||
|
int iconIndex_Computer;
|
||||||
|
const UString name_Computer = RootFolder_GetName_Computer(iconIndex_Computer);
|
||||||
|
|
||||||
|
// const bool is_devicePrefix = (sumPath == L"\\\\.\\");
|
||||||
|
|
||||||
|
if (pathParts.Size() > 1)
|
||||||
|
if (!sumPath.IsEmpty()
|
||||||
|
|| pathParts.Size() != 2
|
||||||
|
|| pathParts[0] != name_Computer)
|
||||||
|
for (unsigned i = 0; i + 1 < pathParts.Size(); i++)
|
||||||
|
{
|
||||||
|
UString name = pathParts[i];
|
||||||
|
sumPath += name;
|
||||||
|
|
||||||
|
bool isRootDir_inLink = false;
|
||||||
|
if (next_Arc_index < _parentFolders.Size())
|
||||||
|
{
|
||||||
|
const CFolderLink &link = _parentFolders[next_Arc_index];
|
||||||
|
if (link.VirtualPath == sumPath)
|
||||||
|
{
|
||||||
|
isRootDir_inLink = true;
|
||||||
|
next_Arc_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int iconIndex = -1;
|
||||||
|
DWORD attrib = isRootDir_inLink ?
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE:
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
if (next_Arc_index == 0
|
||||||
|
|| (next_Arc_index == 1 && isRootDir_inLink))
|
||||||
|
{
|
||||||
|
if (i == 0 && NName::IsDevicePath(us2fs(sumPath)))
|
||||||
|
{
|
||||||
|
UString path = name;
|
||||||
|
path.Add_PathSepar();
|
||||||
|
attrib = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
// FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CFileInfo info;
|
||||||
|
if (info.Find(us2fs(sumPath)))
|
||||||
|
attrib = info.Attrib;
|
||||||
|
}
|
||||||
|
iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(sumPath), attrib);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconIndex < 0)
|
||||||
|
iconIndex = g_Ext_to_Icon_Map.GetIconIndex(attrib, name);
|
||||||
|
// iconIndex = -1; // for debug
|
||||||
|
if (iconIndex < 0 && isRootDir_inLink)
|
||||||
|
iconIndex = 0; // default file
|
||||||
|
|
||||||
|
sumPath.Add_PathSepar();
|
||||||
|
|
||||||
|
ComboBoxPaths.Add(sumPath);
|
||||||
|
if (name.IsEmpty())
|
||||||
|
name.Add_PathSepar();
|
||||||
|
AddComboBoxItem(name, iconIndex, indent++,
|
||||||
false); // addToList
|
false); // addToList
|
||||||
ComboBoxPaths.Add(sumPass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UNDER_CE
|
#ifndef UNDER_CE
|
||||||
|
|
||||||
int iconIndex;
|
|
||||||
UString name;
|
|
||||||
name = RootFolder_GetName_Documents(iconIndex);
|
|
||||||
AddComboBoxItem(name, iconIndex, 0, true);
|
|
||||||
|
|
||||||
name = RootFolder_GetName_Computer(iconIndex);
|
|
||||||
AddComboBoxItem(name, iconIndex, 0, true);
|
|
||||||
|
|
||||||
FStringVector driveStrings;
|
|
||||||
MyGetLogicalDriveStrings(driveStrings);
|
|
||||||
for (i = 0; i < driveStrings.Size(); i++)
|
|
||||||
{
|
{
|
||||||
FString s = driveStrings[i];
|
int iconIndex;
|
||||||
ComboBoxPaths.Add(fs2us(s));
|
const UString name = RootFolder_GetName_Documents(iconIndex);
|
||||||
int iconIndex2 = GetRealIconIndex(s, 0);
|
// iconIndex = -1; // for debug
|
||||||
if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR)
|
AddComboBoxItem(name, iconIndex, 0, true);
|
||||||
s.DeleteBack();
|
}
|
||||||
AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
|
AddComboBoxItem(name_Computer, iconIndex_Computer, 0, true);
|
||||||
|
{
|
||||||
|
FStringVector driveStrings;
|
||||||
|
MyGetLogicalDriveStrings(driveStrings);
|
||||||
|
FOR_VECTOR (i, driveStrings)
|
||||||
|
{
|
||||||
|
FString s = driveStrings[i];
|
||||||
|
ComboBoxPaths.Add(fs2us(s));
|
||||||
|
int iconIndex2 = GetRealIconIndex_for_DirPath(s, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
if (!s.IsEmpty())
|
||||||
|
{
|
||||||
|
const FChar c = s.Back();
|
||||||
|
if (IS_PATH_SEPAR(c))
|
||||||
|
s.DeleteBack();
|
||||||
|
}
|
||||||
|
// iconIndex2 = -1; // for debug
|
||||||
|
AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int iconIndex;
|
||||||
|
const UString name = RootFolder_GetName_Network(iconIndex);
|
||||||
|
AddComboBoxItem(name, iconIndex, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
name = RootFolder_GetName_Network(iconIndex);
|
#endif
|
||||||
AddComboBoxItem(name, iconIndex, 0, true);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -596,10 +805,10 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
|
||||||
int index = _headerComboBox.GetCurSel();
|
int index = _headerComboBox.GetCurSel();
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
UString pass = ComboBoxPaths[index];
|
const UString path = ComboBoxPaths[index];
|
||||||
_headerComboBox.SetCurSel(-1);
|
_headerComboBox.SetCurSel(-1);
|
||||||
// _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
|
// _headerComboBox.SetText(pass); // it's fix for selecting by mouse.
|
||||||
if (BindToPathAndRefresh(pass) == S_OK)
|
if (BindToPathAndRefresh(path) == S_OK)
|
||||||
{
|
{
|
||||||
PostMsg(kSetFocusToListView);
|
PostMsg(kSetFocusToListView);
|
||||||
#ifdef UNDER_CE
|
#ifdef UNDER_CE
|
||||||
|
|
|
||||||
|
|
@ -583,8 +583,13 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||||
int cursorIndex = -1;
|
int cursorIndex = -1;
|
||||||
|
|
||||||
CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
|
CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
|
||||||
|
#if 1 // 0 : for debug local icons loading
|
||||||
if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
|
if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
|
||||||
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
|
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const bool isFSDrivesFolder = IsFSDrivesFolder();
|
||||||
|
const bool isArcFolder = IsArcFolder();
|
||||||
|
|
||||||
if (!IsFSFolder())
|
if (!IsFSFolder())
|
||||||
{
|
{
|
||||||
|
|
@ -631,10 +636,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||||
#else
|
#else
|
||||||
item.pszText = LPSTR_TEXTCALLBACKW;
|
item.pszText = LPSTR_TEXTCALLBACKW;
|
||||||
#endif
|
#endif
|
||||||
const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
|
// const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||||
item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
|
item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
|
||||||
|
// g_Ext_to_Icon_Map.GetIconIndex(attrib, itemName);
|
||||||
if (item.iImage < 0)
|
if (item.iImage < 0)
|
||||||
item.iImage = 0;
|
item.iImage = 0;
|
||||||
if (_listView.InsertItem(&item) == -1)
|
if (_listView.InsertItem(&item) == -1)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
listViewItemCount++;
|
listViewItemCount++;
|
||||||
|
|
@ -755,11 +761,52 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool defined = false;
|
bool defined = false;
|
||||||
|
item.iImage = -1;
|
||||||
|
|
||||||
if (folderGetSystemIconIndex)
|
if (folderGetSystemIconIndex)
|
||||||
{
|
{
|
||||||
folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
|
const HRESULT res = folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
|
||||||
defined = (item.iImage > 0);
|
if (res == S_OK)
|
||||||
|
{
|
||||||
|
// item.iImage = -1; // for debug
|
||||||
|
defined = (item.iImage > 0);
|
||||||
|
#if 0 // 0: can be slower: 2 attempts for some paths.
|
||||||
|
// 1: faster, but we can get default icon for some cases (where non default icon is possible)
|
||||||
|
|
||||||
|
if (item.iImage == 0)
|
||||||
|
{
|
||||||
|
// (item.iImage == 0) means default icon.
|
||||||
|
// But (item.iImage == 0) also can be returned for exe/ico files,
|
||||||
|
// if filePath is LONG PATH (path_len() >= MAX_PATH).
|
||||||
|
// Also we want to show split icon (.001) for any split extension: 001 002 003.
|
||||||
|
// Are there another cases for (item.iImage == 0) for files with known extensions?
|
||||||
|
// We don't want to do second attempt to request icon,
|
||||||
|
// if it also will return (item.iImage == 0).
|
||||||
|
|
||||||
|
int dotPos = -1;
|
||||||
|
for (unsigned k = 0;; k++)
|
||||||
|
{
|
||||||
|
const wchar_t c = name[k];
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
if (c == '.')
|
||||||
|
dotPos = (int)i;
|
||||||
|
// we don't need IS_PATH_SEPAR check, because we have only (fileName) doesn't include path prefix.
|
||||||
|
// if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;
|
||||||
|
}
|
||||||
|
defined = true;
|
||||||
|
if (dotPos >= 0)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
const wchar_t *ext = name + dotPos;
|
||||||
|
if (StringsAreEqualNoCase_Ascii(ext, ".exe") ||
|
||||||
|
StringsAreEqualNoCase_Ascii(ext, ".ico"))
|
||||||
|
#endif
|
||||||
|
defined = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!defined)
|
if (!defined)
|
||||||
|
|
@ -769,26 +816,37 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||||
NCOM::CPropVariant prop;
|
NCOM::CPropVariant prop;
|
||||||
RINOK(_folder->GetProperty(i, kpidAttrib, &prop))
|
RINOK(_folder->GetProperty(i, kpidAttrib, &prop))
|
||||||
if (prop.vt == VT_UI4)
|
if (prop.vt == VT_UI4)
|
||||||
|
{
|
||||||
attrib = prop.ulVal;
|
attrib = prop.ulVal;
|
||||||
|
if (isArcFolder)
|
||||||
|
{
|
||||||
|
// if attrib (high 16-bits) is supposed from posix,
|
||||||
|
// we keep only low bits (basic Windows attrib flags):
|
||||||
|
if (attrib & 0xF0000000)
|
||||||
|
attrib &= 0x3FFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (IsItem_Folder(i))
|
if (IsItem_Folder(i))
|
||||||
attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
attrib |= FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
|
||||||
if (_currentFolderPrefix.IsEmpty())
|
|
||||||
{
|
|
||||||
int iconIndexTemp;
|
|
||||||
GetRealIconIndex(us2fs((UString)name) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);
|
|
||||||
item.iImage = iconIndexTemp;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
attrib &= ~(UInt32)FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
|
||||||
|
item.iImage = -1;
|
||||||
|
if (isFSDrivesFolder)
|
||||||
{
|
{
|
||||||
item.iImage = _extToIconMap.GetIconIndex(attrib, name);
|
FString fs (us2fs((UString)name));
|
||||||
|
fs.Add_PathSepar();
|
||||||
|
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(fs, attrib);
|
||||||
|
// item.iImage = 0; // for debug
|
||||||
}
|
}
|
||||||
|
if (item.iImage < 0) // <= 0 check?
|
||||||
|
item.iImage = g_Ext_to_Icon_Map.GetIconIndex(attrib, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// item.iImage = -1; // for debug
|
||||||
if (item.iImage < 0)
|
if (item.iImage < 0)
|
||||||
item.iImage = 0;
|
item.iImage = 0; // default image
|
||||||
|
|
||||||
if (_listView.InsertItem(&item) == -1)
|
if (_listView.InsertItem(&item) == -1)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
listViewItemCount++;
|
listViewItemCount++;
|
||||||
|
|
@ -858,8 +916,8 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
|
||||||
sprintf(s,
|
sprintf(s,
|
||||||
// "attribMap = %5d, extMap = %5d, "
|
// "attribMap = %5d, extMap = %5d, "
|
||||||
"delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d",
|
"delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d",
|
||||||
// _extToIconMap._attribMap.Size(),
|
// g_Ext_to_Icon_Map._attribMap.Size(),
|
||||||
// _extToIconMap._extMap.Size(),
|
// g_Ext_to_Icon_Map._extMap.Size(),
|
||||||
tickCount1 - tickCount0,
|
tickCount1 - tickCount0,
|
||||||
tickCount2 - tickCount1,
|
tickCount2 - tickCount1,
|
||||||
tickCount3 - tickCount2,
|
tickCount3 - tickCount2,
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,9 @@ UString RootFolder_GetName_Computer(int &iconIndex);
|
||||||
UString RootFolder_GetName_Computer(int &iconIndex)
|
UString RootFolder_GetName_Computer(int &iconIndex)
|
||||||
{
|
{
|
||||||
#ifdef USE_WIN_PATHS
|
#ifdef USE_WIN_PATHS
|
||||||
iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
|
iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
|
||||||
#else
|
#else
|
||||||
GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
|
iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY);
|
||||||
#endif
|
#endif
|
||||||
return LangString(IDS_COMPUTER);
|
return LangString(IDS_COMPUTER);
|
||||||
}
|
}
|
||||||
|
|
@ -64,14 +64,14 @@ UString RootFolder_GetName_Computer(int &iconIndex)
|
||||||
UString RootFolder_GetName_Network(int &iconIndex);
|
UString RootFolder_GetName_Network(int &iconIndex);
|
||||||
UString RootFolder_GetName_Network(int &iconIndex)
|
UString RootFolder_GetName_Network(int &iconIndex)
|
||||||
{
|
{
|
||||||
iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK);
|
iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_NETWORK);
|
||||||
return LangString(IDS_NETWORK);
|
return LangString(IDS_NETWORK);
|
||||||
}
|
}
|
||||||
|
|
||||||
UString RootFolder_GetName_Documents(int &iconIndex);
|
UString RootFolder_GetName_Documents(int &iconIndex);
|
||||||
UString RootFolder_GetName_Documents(int &iconIndex)
|
UString RootFolder_GetName_Documents(int &iconIndex)
|
||||||
{
|
{
|
||||||
iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL);
|
iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_PERSONAL);
|
||||||
return LangString(IDS_DOCUMENTS);
|
return LangString(IDS_DOCUMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,7 +96,7 @@ void CRootFolder::Init()
|
||||||
_names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
|
_names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
|
||||||
_names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
|
_names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
|
||||||
_names[ROOT_INDEX_VOLUMES] = kVolPrefix;
|
_names[ROOT_INDEX_VOLUMES] = kVolPrefix;
|
||||||
_iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES);
|
_iconIndices[ROOT_INDEX_VOLUMES] = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,19 @@
|
||||||
extern bool g_IsNT;
|
extern bool g_IsNT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int GetIconIndexForCSIDL(int csidl)
|
CExtToIconMap g_Ext_to_Icon_Map;
|
||||||
|
|
||||||
|
int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)
|
||||||
{
|
{
|
||||||
LPITEMIDLIST pidl = NULL;
|
LPITEMIDLIST pidl = NULL;
|
||||||
SHGetSpecialFolderLocation(NULL, csidl, &pidl);
|
SHGetSpecialFolderLocation(NULL, csidl, &pidl);
|
||||||
if (pidl)
|
if (pidl)
|
||||||
{
|
{
|
||||||
SHFILEINFO shellInfo;
|
SHFILEINFO shFileInfo;
|
||||||
shellInfo.iIcon = 0;
|
shFileInfo.iIcon = -1;
|
||||||
const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL,
|
const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl),
|
||||||
&shellInfo, sizeof(shellInfo),
|
FILE_ATTRIBUTE_DIRECTORY,
|
||||||
|
&shFileInfo, sizeof(shFileInfo),
|
||||||
SHGFI_PIDL | SHGFI_SYSICONINDEX);
|
SHGFI_PIDL | SHGFI_SYSICONINDEX);
|
||||||
/*
|
/*
|
||||||
IMalloc *pMalloc;
|
IMalloc *pMalloc;
|
||||||
|
|
@ -43,9 +46,9 @@ int GetIconIndexForCSIDL(int csidl)
|
||||||
// we use OLE2.dll function here
|
// we use OLE2.dll function here
|
||||||
CoTaskMemFree(pidl);
|
CoTaskMemFree(pidl);
|
||||||
if (res)
|
if (res)
|
||||||
return shellInfo.iIcon;
|
return shFileInfo.iIcon;
|
||||||
}
|
}
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
|
|
@ -60,69 +63,111 @@ static struct C_SHGetFileInfo_Init
|
||||||
f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
|
f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
|
||||||
Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
|
Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
|
||||||
"SHGetFileInfoW");
|
"SHGetFileInfoW");
|
||||||
|
// f_SHGetFileInfoW = NULL; // for debug
|
||||||
}
|
}
|
||||||
} g_SHGetFileInfo_Init;
|
} g_SHGetFileInfo_Init;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _UNICODE
|
||||||
|
#define My_SHGetFileInfoW SHGetFileInfoW
|
||||||
|
#else
|
||||||
static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
|
static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
|
||||||
{
|
{
|
||||||
#ifdef _UNICODE
|
|
||||||
return SHGetFileInfo
|
|
||||||
#else
|
|
||||||
if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)
|
if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)
|
||||||
return 0;
|
return 0;
|
||||||
return g_SHGetFileInfo_Init.f_SHGetFileInfoW
|
return g_SHGetFileInfo_Init.f_SHGetFileInfoW(pszPath, attrib, psfi, cbFileInfo, uFlags);
|
||||||
#endif
|
|
||||||
(pszPath, attrib, psfi, cbFileInfo, uFlags);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex)
|
DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
|
||||||
|
CFSTR path, DWORD attrib, int &iconIndex)
|
||||||
{
|
{
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
if (!g_IsNT)
|
if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW)
|
||||||
{
|
{
|
||||||
SHFILEINFO shellInfo;
|
SHFILEINFO shFileInfo;
|
||||||
const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
// ZeroMemory(&shFileInfo, sizeof(shFileInfo));
|
||||||
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
shFileInfo.iIcon = -1; // optional
|
||||||
iconIndex = shellInfo.iIcon;
|
const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path),
|
||||||
|
attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
|
||||||
|
&shFileInfo, sizeof(shFileInfo),
|
||||||
|
SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
||||||
|
iconIndex = shFileInfo.iIcon;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
SHFILEINFOW shellInfo;
|
SHFILEINFOW shFileInfo;
|
||||||
const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
// ZeroMemory(&shFileInfo, sizeof(shFileInfo));
|
||||||
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
shFileInfo.iIcon = -1; // optional
|
||||||
iconIndex = shellInfo.iIcon;
|
const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path),
|
||||||
|
attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
|
||||||
|
&shFileInfo, sizeof(shFileInfo),
|
||||||
|
SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
|
||||||
|
// (shFileInfo.iIcon == 0) returned for unknown extensions and files without extension
|
||||||
|
iconIndex = shFileInfo.iIcon;
|
||||||
|
// we use SHGFI_USEFILEATTRIBUTES, and
|
||||||
|
// (res != 0) is expected for main cases, even if there are no such file.
|
||||||
|
// (res == 0) for path with kSuperPrefix \\?\
|
||||||
|
// Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe.
|
||||||
|
// So we can use SHGFI_USEFILEATTRIBUTES for any case.
|
||||||
|
// UString temp = fs2us(path); // for debug
|
||||||
|
// UString tempName = temp.Ptr(temp.ReverseFind_PathSepar() + 1); // for debug
|
||||||
|
// iconIndex = -1; // for debug
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib)
|
||||||
|
{
|
||||||
|
int iconIndex = -1;
|
||||||
|
if (!Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
|
||||||
|
path, attrib, iconIndex))
|
||||||
|
iconIndex = -1;
|
||||||
|
return iconIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
|
CFSTR path, DWORD attrib, Int32 *iconIndex)
|
||||||
|
{
|
||||||
|
*iconIndex = -1;
|
||||||
|
int iconIndexTemp;
|
||||||
|
if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
|
||||||
|
path, attrib, iconIndexTemp))
|
||||||
|
{
|
||||||
|
*iconIndex = iconIndexTemp;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return GetLastError_noZero_HRESULT();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
|
DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
|
||||||
{
|
{
|
||||||
#ifndef _UNICODE
|
#ifndef _UNICODE
|
||||||
if (!g_IsNT)
|
if (!g_IsNT)
|
||||||
{
|
{
|
||||||
SHFILEINFO shellInfo;
|
SHFILEINFO shFileInfo;
|
||||||
shellInfo.szTypeName[0] = 0;
|
shFileInfo.szTypeName[0] = 0;
|
||||||
DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
|
||||||
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
||||||
if (typeName)
|
if (typeName)
|
||||||
*typeName = GetUnicodeString(shellInfo.szTypeName);
|
*typeName = GetUnicodeString(shFileInfo.szTypeName);
|
||||||
iconIndex = shellInfo.iIcon;
|
iconIndex = shFileInfo.iIcon;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
SHFILEINFOW shellInfo;
|
SHFILEINFOW shFileInfo;
|
||||||
shellInfo.szTypeName[0] = 0;
|
shFileInfo.szTypeName[0] = 0;
|
||||||
DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
|
DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
|
||||||
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
|
||||||
if (typeName)
|
if (typeName)
|
||||||
*typeName = shellInfo.szTypeName;
|
*typeName = shFileInfo.szTypeName;
|
||||||
iconIndex = shellInfo.iIcon;
|
iconIndex = shFileInfo.iIcon;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -164,6 +209,9 @@ static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// bool DoItemAlwaysStart(const UString &name);
|
||||||
|
|
||||||
int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
|
int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
|
||||||
{
|
{
|
||||||
int dotPos = -1;
|
int dotPos = -1;
|
||||||
|
|
@ -175,6 +223,8 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
|
||||||
break;
|
break;
|
||||||
if (c == '.')
|
if (c == '.')
|
||||||
dotPos = (int)i;
|
dotPos = (int)i;
|
||||||
|
// we don't need IS_PATH_SEPAR check, because (fileName) doesn't include path prefix.
|
||||||
|
// if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -187,8 +237,11 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)
|
if ((attrib & FILE_ATTRIBUTE_DIRECTORY) || dotPos < 0)
|
||||||
|
for (unsigned k = 0;; k++)
|
||||||
{
|
{
|
||||||
|
if (k >= 2)
|
||||||
|
return -1;
|
||||||
unsigned insertPos = 0;
|
unsigned insertPos = 0;
|
||||||
const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
|
const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
|
|
@ -197,33 +250,43 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
|
||||||
return _attribMap[(unsigned)index].IconIndex;
|
return _attribMap[(unsigned)index].IconIndex;
|
||||||
}
|
}
|
||||||
CAttribIconPair pair;
|
CAttribIconPair pair;
|
||||||
GetRealIconIndex(
|
pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
|
||||||
#ifdef UNDER_CE
|
#ifdef UNDER_CE
|
||||||
FTEXT("\\")
|
FTEXT("\\")
|
||||||
#endif
|
#endif
|
||||||
FTEXT("__DIR__")
|
FTEXT("__DIR__")
|
||||||
, attrib, pair.IconIndex
|
, attrib
|
||||||
// , pair.TypeName
|
// , pair.TypeName
|
||||||
);
|
);
|
||||||
|
if (_attribMap.Size() < (1u << 16) // we limit cache size
|
||||||
/*
|
|| attrib < (1u << 15)) // we want to put all items with basic attribs to cache
|
||||||
char s[256];
|
{
|
||||||
sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
|
/*
|
||||||
OutputDebugStringA(s);
|
char s[256];
|
||||||
*/
|
sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
|
||||||
|
OutputDebugStringA(s);
|
||||||
pair.Attrib = attrib;
|
*/
|
||||||
_attribMap.Insert(insertPos, pair);
|
pair.Attrib = attrib;
|
||||||
// if (typeName) *typeName = pair.TypeName;
|
_attribMap.Insert(insertPos, pair);
|
||||||
return pair.IconIndex;
|
// if (typeName) *typeName = pair.TypeName;
|
||||||
|
return pair.IconIndex;
|
||||||
|
}
|
||||||
|
if (pair.IconIndex >= 0)
|
||||||
|
return pair.IconIndex;
|
||||||
|
attrib = (attrib & FILE_ATTRIBUTE_DIRECTORY) ?
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY :
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CObjectVector<CExtIconPair> &map =
|
||||||
|
(attrib & FILE_ATTRIBUTE_COMPRESSED) ?
|
||||||
|
_extMap_Compressed : _extMap_Normal;
|
||||||
const wchar_t *ext = fileName + dotPos + 1;
|
const wchar_t *ext = fileName + dotPos + 1;
|
||||||
unsigned insertPos = 0;
|
unsigned insertPos = 0;
|
||||||
const int index = FindInSorted_Ext(_extMap, ext, insertPos);
|
const int index = FindInSorted_Ext(map, ext, insertPos);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
const CExtIconPair &pa = _extMap[index];
|
const CExtIconPair &pa = map[index];
|
||||||
// if (typeName) *typeName = pa.TypeName;
|
// if (typeName) *typeName = pa.TypeName;
|
||||||
return pa.IconIndex;
|
return pa.IconIndex;
|
||||||
}
|
}
|
||||||
|
|
@ -238,14 +301,14 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
|
||||||
}
|
}
|
||||||
if (i != 0 && ext[i] == 0)
|
if (i != 0 && ext[i] == 0)
|
||||||
{
|
{
|
||||||
// GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003
|
// Shell_GetFileInfo_SysIconIndex_for_Path is too slow for big number of split extensions: .001, .002, .003
|
||||||
if (!SplitIconIndex_Defined)
|
if (!SplitIconIndex_Defined)
|
||||||
{
|
{
|
||||||
GetRealIconIndex(
|
Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
|
||||||
#ifdef UNDER_CE
|
#ifdef UNDER_CE
|
||||||
FTEXT("\\")
|
FTEXT("\\")
|
||||||
#endif
|
#endif
|
||||||
FTEXT("__FILE__.001"), 0, SplitIconIndex);
|
FTEXT("__FILE__.001"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex);
|
||||||
SplitIconIndex_Defined = true;
|
SplitIconIndex_Defined = true;
|
||||||
}
|
}
|
||||||
return SplitIconIndex;
|
return SplitIconIndex;
|
||||||
|
|
@ -253,27 +316,36 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
|
||||||
|
|
||||||
CExtIconPair pair;
|
CExtIconPair pair;
|
||||||
pair.Ext = ext;
|
pair.Ext = ext;
|
||||||
GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);
|
pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
|
||||||
_extMap.Insert(insertPos, pair);
|
us2fs(fileName + dotPos),
|
||||||
|
attrib & FILE_ATTRIBUTE_COMPRESSED ?
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED:
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE);
|
||||||
|
if (map.Size() < (1u << 16) // we limit cache size
|
||||||
|
// || DoItemAlwaysStart(fileName + dotPos) // we want some popular extensions in cache
|
||||||
|
)
|
||||||
|
map.Insert(insertPos, pair);
|
||||||
// if (typeName) *typeName = pair.TypeName;
|
// if (typeName) *typeName = pair.TypeName;
|
||||||
return pair.IconIndex;
|
return pair.IconIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
|
|
||||||
{
|
|
||||||
return GetIconIndex(attrib, fileName, NULL);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
HIMAGELIST GetSysImageList(bool smallIcons)
|
HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons)
|
||||||
{
|
{
|
||||||
SHFILEINFO shellInfo;
|
SHFILEINFO shFileInfo;
|
||||||
return (HIMAGELIST)SHGetFileInfo(TEXT(""),
|
// shFileInfo.hIcon = NULL; // optional
|
||||||
FILE_ATTRIBUTE_NORMAL |
|
const DWORD_PTR res = SHGetFileInfo(TEXT(""),
|
||||||
|
/* FILE_ATTRIBUTE_ARCHIVE | */
|
||||||
FILE_ATTRIBUTE_DIRECTORY,
|
FILE_ATTRIBUTE_DIRECTORY,
|
||||||
&shellInfo, sizeof(shellInfo),
|
&shFileInfo, sizeof(shFileInfo),
|
||||||
SHGFI_USEFILEATTRIBUTES |
|
SHGFI_USEFILEATTRIBUTES |
|
||||||
SHGFI_SYSICONINDEX |
|
SHGFI_SYSICONINDEX |
|
||||||
(smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));
|
(smallIcons ? SHGFI_SMALLICON : SHGFI_LARGEICON));
|
||||||
|
#if 0
|
||||||
|
// (shFileInfo.hIcon == NULL), because we don't use SHGFI_ICON.
|
||||||
|
// so DestroyIcon() is not required
|
||||||
|
if (res && shFileInfo.hIcon) // unexpected
|
||||||
|
DestroyIcon(shFileInfo.hIcon);
|
||||||
|
#endif
|
||||||
|
return (HIMAGELIST)res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ struct CExtIconPair
|
||||||
UString Ext;
|
UString Ext;
|
||||||
int IconIndex;
|
int IconIndex;
|
||||||
// UString TypeName;
|
// UString TypeName;
|
||||||
|
|
||||||
// int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
|
// int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -23,15 +22,15 @@ struct CAttribIconPair
|
||||||
DWORD Attrib;
|
DWORD Attrib;
|
||||||
int IconIndex;
|
int IconIndex;
|
||||||
// UString TypeName;
|
// UString TypeName;
|
||||||
|
|
||||||
// int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
|
// int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class CExtToIconMap
|
|
||||||
|
struct CExtToIconMap
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
CRecordVector<CAttribIconPair> _attribMap;
|
CRecordVector<CAttribIconPair> _attribMap;
|
||||||
CObjectVector<CExtIconPair> _extMap;
|
CObjectVector<CExtIconPair> _extMap_Normal;
|
||||||
|
CObjectVector<CExtIconPair> _extMap_Compressed;
|
||||||
int SplitIconIndex;
|
int SplitIconIndex;
|
||||||
int SplitIconIndex_Defined;
|
int SplitIconIndex_Defined;
|
||||||
|
|
||||||
|
|
@ -40,16 +39,27 @@ public:
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
SplitIconIndex_Defined = false;
|
SplitIconIndex_Defined = false;
|
||||||
_extMap.Clear();
|
_extMap_Normal.Clear();
|
||||||
|
_extMap_Compressed.Clear();
|
||||||
_attribMap.Clear();
|
_attribMap.Clear();
|
||||||
}
|
}
|
||||||
|
int GetIconIndex_DIR(DWORD attrib = FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
return GetIconIndex(attrib, L"__DIR__");
|
||||||
|
}
|
||||||
int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);
|
int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);
|
||||||
// int GetIconIndex(DWORD attrib, const UString &fileName);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex);
|
extern CExtToIconMap g_Ext_to_Icon_Map;
|
||||||
int GetIconIndexForCSIDL(int csidl);
|
|
||||||
|
|
||||||
HIMAGELIST GetSysImageList(bool smallIcons);
|
DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
|
||||||
|
CFSTR path, DWORD attrib, int &iconIndex);
|
||||||
|
HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
|
||||||
|
CFSTR path, DWORD attrib, Int32 *iconIndex);
|
||||||
|
int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib);
|
||||||
|
|
||||||
|
int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl);
|
||||||
|
|
||||||
|
HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -387,13 +387,13 @@ void CApp::VerCtrl(unsigned id)
|
||||||
*/
|
*/
|
||||||
COverwriteDialog dialog;
|
COverwriteDialog dialog;
|
||||||
|
|
||||||
dialog.OldFileInfo.SetTime(&fdi.Info.ftLastWriteTime);
|
dialog.OldFileInfo.SetTime(fdi.Info.ftLastWriteTime);
|
||||||
dialog.OldFileInfo.SetSize(fdi.GetSize());
|
dialog.OldFileInfo.SetSize(fdi.GetSize());
|
||||||
dialog.OldFileInfo.Name = fs2us(path);
|
dialog.OldFileInfo.Path = fs2us(path);
|
||||||
|
|
||||||
dialog.NewFileInfo.SetTime(&fdi2.Info.ftLastWriteTime);
|
dialog.NewFileInfo.SetTime(fdi2.Info.ftLastWriteTime);
|
||||||
dialog.NewFileInfo.SetSize(fdi2.GetSize());
|
dialog.NewFileInfo.SetSize(fdi2.GetSize());
|
||||||
dialog.NewFileInfo.Name = fs2us(path2);
|
dialog.NewFileInfo.Path = fs2us(path2);
|
||||||
|
|
||||||
dialog.ShowExtraButtons = false;
|
dialog.ShowExtraButtons = false;
|
||||||
dialog.DefaultButton_is_NO = true;
|
dialog.DefaultButton_is_NO = true;
|
||||||
|
|
|
||||||
|
|
@ -66,28 +66,6 @@ void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AddSizeValue(UString &s, UInt64 value)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
wchar_t sz[32];
|
|
||||||
ConvertUInt64ToString(value, sz);
|
|
||||||
s += MyFormatNew(IDS_FILE_SIZE, sz);
|
|
||||||
}
|
|
||||||
if (value >= (1 << 10))
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }
|
|
||||||
else if (value >= (10 << 20)) { value >>= 20; c = 'M'; }
|
|
||||||
else { value >>= 10; c = 'K'; }
|
|
||||||
|
|
||||||
s += " (";
|
|
||||||
s.Add_UInt64(value);
|
|
||||||
s.Add_Space();
|
|
||||||
s += (wchar_t)c;
|
|
||||||
s += "iB)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
|
void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
|
||||||
{
|
{
|
||||||
CProperty &pair = pairs.AddNew();
|
CProperty &pair = pairs.AddNew();
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,31 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool Is_File_LimitedBy_4GB(CFSTR _path, bool &isFsDetected)
|
||||||
|
{
|
||||||
|
isFsDetected = false;
|
||||||
|
FString path (_path);
|
||||||
|
path.DeleteFrom(NName::GetRootPrefixSize(path));
|
||||||
|
// GetVolumeInformation supports super paths.
|
||||||
|
// NName::If_IsSuperPath_RemoveSuperPrefix(path);
|
||||||
|
if (!path.IsEmpty())
|
||||||
|
{
|
||||||
|
DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags;
|
||||||
|
UString volName, fileSystemName;
|
||||||
|
if (MyGetVolumeInformation(path, volName,
|
||||||
|
&volumeSerialNumber, &maximumComponentLength, &fileSystemFlags,
|
||||||
|
fileSystemName))
|
||||||
|
{
|
||||||
|
isFsDetected = true;
|
||||||
|
if (fileSystemName.IsPrefixedBy_Ascii_NoCase("fat"))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "../../C/CpuArch.h"
|
#include "../../C/CpuArch.h"
|
||||||
|
|
||||||
#include "../Common/IntToString.h"
|
#include "../Common/IntToString.h"
|
||||||
|
#include "../Common/StringConvert.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
|
@ -511,8 +512,6 @@ void GetSysInfo(AString &s1, AString &s2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GetCpuName(AString &s);
|
|
||||||
|
|
||||||
static void AddBracedString(AString &dest, AString &src)
|
static void AddBracedString(AString &dest, AString &src)
|
||||||
{
|
{
|
||||||
if (!src.IsEmpty())
|
if (!src.IsEmpty())
|
||||||
|
|
@ -554,9 +553,7 @@ void CCpuName::Fill()
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
{
|
{
|
||||||
#if !defined(MY_CPU_AMD64)
|
#if !defined(MY_CPU_AMD64)
|
||||||
if (!z7_x86_cpuid_GetMaxFunc())
|
if (z7_x86_cpuid_GetMaxFunc())
|
||||||
s += "x86";
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
x86cpuid_to_String(s);
|
x86cpuid_to_String(s);
|
||||||
|
|
@ -583,43 +580,26 @@ void CCpuName::Fill()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (s.IsEmpty())
|
#ifdef _WIN32
|
||||||
{
|
|
||||||
#ifdef MY_CPU_LE
|
|
||||||
s += "LE";
|
|
||||||
#elif defined(MY_CPU_BE)
|
|
||||||
s += "BE";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
{
|
|
||||||
AString s2;
|
|
||||||
UInt32 v = 0;
|
|
||||||
if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
|
|
||||||
{
|
|
||||||
s2.Add_UInt32(v);
|
|
||||||
s2 += 'C';
|
|
||||||
}
|
|
||||||
if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
|
|
||||||
{
|
|
||||||
s2.Add_UInt32(v);
|
|
||||||
s2 += 'T';
|
|
||||||
}
|
|
||||||
if (!s2.IsEmpty())
|
|
||||||
{
|
|
||||||
s.Add_Space_if_NotEmpty();
|
|
||||||
s += s2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
{
|
{
|
||||||
NRegistry::CKey key;
|
NRegistry::CKey key;
|
||||||
if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
|
if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
// s.Empty(); // for debug
|
||||||
|
{
|
||||||
|
CSysString name;
|
||||||
|
if (s.IsEmpty())
|
||||||
|
if (key.QueryValue(TEXT("ProcessorNameString"), name) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
s += GetAnsiString(name);
|
||||||
|
}
|
||||||
|
if (key.QueryValue(TEXT("Identifier"), name) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
if (!Revision.IsEmpty())
|
||||||
|
Revision += " : ";
|
||||||
|
Revision += GetAnsiString(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
LONG res[2];
|
LONG res[2];
|
||||||
CByteBuffer bufs[2];
|
CByteBuffer bufs[2];
|
||||||
{
|
{
|
||||||
|
|
@ -627,8 +607,9 @@ void CCpuName::Fill()
|
||||||
{
|
{
|
||||||
UInt32 size = 0;
|
UInt32 size = 0;
|
||||||
res[i] = key.QueryValue(i == 0 ?
|
res[i] = key.QueryValue(i == 0 ?
|
||||||
TEXT("Previous Update Revision") :
|
TEXT("Previous Update Revision") :
|
||||||
TEXT("Update Revision"), bufs[i], size);
|
TEXT("Update Revision"),
|
||||||
|
bufs[i], size);
|
||||||
if (res[i] == ERROR_SUCCESS)
|
if (res[i] == ERROR_SUCCESS)
|
||||||
if (size != bufs[i].Size())
|
if (size != bufs[i].Size())
|
||||||
res[i] = ERROR_SUCCESS + 1;
|
res[i] = ERROR_SUCCESS + 1;
|
||||||
|
|
@ -657,8 +638,36 @@ void CCpuName::Fill()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (s.IsEmpty())
|
||||||
|
{
|
||||||
|
#ifdef MY_CPU_NAME
|
||||||
|
s += MY_CPU_NAME;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
{
|
||||||
|
AString s2;
|
||||||
|
UInt32 v = 0;
|
||||||
|
if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
|
||||||
|
{
|
||||||
|
s2.Add_UInt32(v);
|
||||||
|
s2.Add_Char('C');
|
||||||
|
}
|
||||||
|
if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
|
||||||
|
{
|
||||||
|
s2.Add_UInt32(v);
|
||||||
|
s2.Add_Char('T');
|
||||||
|
}
|
||||||
|
if (!s2.IsEmpty())
|
||||||
|
{
|
||||||
|
s.Add_Space_if_NotEmpty();
|
||||||
|
s += s2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Z7_LARGE_PAGES
|
#ifdef Z7_LARGE_PAGES
|
||||||
Add_LargePages_String(LargePages);
|
Add_LargePages_String(LargePages);
|
||||||
|
|
@ -900,7 +909,7 @@ void GetSystemInfoText(AString &sRes)
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
AString s;
|
AString s;
|
||||||
GetCpuName(s);
|
GetCpuName_MultiLine(s);
|
||||||
if (!s.IsEmpty())
|
if (!s.IsEmpty())
|
||||||
{
|
{
|
||||||
sRes += s;
|
sRes += s;
|
||||||
|
|
@ -923,18 +932,6 @@ void GetSystemInfoText(AString &sRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GetCpuName(AString &s);
|
|
||||||
void GetCpuName(AString &s)
|
|
||||||
{
|
|
||||||
CCpuName cpuName;
|
|
||||||
cpuName.Fill();
|
|
||||||
s = cpuName.CpuName;
|
|
||||||
AString s2;
|
|
||||||
cpuName.Get_Revision_Microcode_LargePages(s2);
|
|
||||||
s.Add_OptSpaced(s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void GetCpuName_MultiLine(AString &s);
|
void GetCpuName_MultiLine(AString &s);
|
||||||
void GetCpuName_MultiLine(AString &s)
|
void GetCpuName_MultiLine(AString &s)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
<?define VerMajor = "24" ?>
|
<?define VerMajor = "24" ?>
|
||||||
<?define VerMinor = "07" ?>
|
<?define VerMinor = "08" ?>
|
||||||
<?define VerBuild = "00" ?>
|
<?define VerBuild = "00" ?>
|
||||||
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
|
||||||
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
HISTORY of the 7-Zip source code
|
HISTORY of the 7-Zip source code
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
24.08 2024-08-11
|
||||||
|
-------------------------
|
||||||
|
- The bug in 7-Zip 24.00-24.07 was fixed:
|
||||||
|
For creating a zip archive: 7-Zip could write extra zero bytes after the end of the archive,
|
||||||
|
if a file included to archive cannot be compressed to a size smaller than original.
|
||||||
|
The created zip archive is correct except for the useless zero bytes after the end of the archive.
|
||||||
|
When unpacking such a zip archive, 7-Zip displays a warning:
|
||||||
|
"WARNING: There are data after the end of archive".
|
||||||
|
- Some bugs were fixed.
|
||||||
|
|
||||||
|
|
||||||
24.07 2024-06-19
|
24.07 2024-06-19
|
||||||
-------------------------
|
-------------------------
|
||||||
- Changes in files:
|
- Changes in files:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue