This commit is contained in:
Igor Pavlov 2024-08-11 00:00:00 +00:00
parent a7a1d4a241
commit e008ce3976
42 changed files with 1567 additions and 799 deletions

View file

@ -1,7 +1,7 @@
#define MY_VER_MAJOR 24
#define MY_VER_MINOR 07
#define MY_VER_MINOR 8
#define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "24.07"
#define MY_VERSION_NUMBERS "24.08"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
#define MY_DATE "2024-06-19"
#define MY_DATE "2024-08-11"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"

View file

@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code
2024-05-18 : Igor Pavlov : Public domain */
2024-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
@ -848,7 +848,11 @@ static unsigned long MY_getauxval(int aux)
#define MY_HWCAP_CHECK_FUNC(name) \
BoolInt CPU_IsSupported_ ## name(void) { return 0; }
#if defined(__ARM_NEON)
BoolInt CPU_IsSupported_NEON(void) { return True; }
#else
MY_HWCAP_CHECK_FUNC(NEON)
#endif
#endif // USE_HWCAP

View file

@ -628,6 +628,7 @@ static const char * const g_Machines[] =
static const CUInt32PCharPair g_MachinePairs[] =
{
{ 243, "RISC-V" },
{ 258, "LoongArch" },
{ 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
{ 0xbaab, "Xilinx MicroBlaze" }
};
@ -853,10 +854,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
else if (_header.Machine == k_Machine_MIPS)
{
const UInt32 ver = flags >> 28;
s += "v";
s.Add_Char('v');
s.Add_UInt32(ver);
flags &= ((UInt32)1 << 28) - 1;
const UInt32 abi = (flags >> 12) & 7;
if (abi)
{
@ -864,7 +864,6 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
s.Add_UInt32(abi);
}
flags &= ~((UInt32)7 << 12);
s.Add_Space();
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;
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
{
char sz[16];

View file

@ -111,6 +111,12 @@ static const CPartType kPartTypes[] =
{ 0x0FC63DAF, NULL, "Linux Data" },
{ 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" },
{ 0x516E7CB4, NULL, "FreeBSD Data" },

View file

@ -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
{
kDirLink_EXCEPTION = 3,
kDirLink_Certificate = 4,
kDirLink_BASERELOC = 5,
kDirLink_Debug = 6
};
@ -229,7 +252,7 @@ struct COptHeader
UInt32 UninitDataSize;
// UInt32 AddressOfEntryPoint;
// UInt32 BaseOfCode;
// UInt32 BaseOfCode; // VA(.text) == 0x1000 in most cases
// UInt32 BaseOfData32;
UInt64 ImageBase;
@ -273,6 +296,7 @@ struct COptHeader
}
};
// size is 16-bit
bool COptHeader::Parse(const Byte *p, UInt32 size)
{
if (size < k_OptHeader32_Size_MIN)
@ -334,14 +358,18 @@ bool COptHeader::Parse(const Byte *p, UInt32 size)
pos = 92;
}
G32(pos, NumDirItems);
if (NumDirItems > (1 << 16))
UInt32 numDirItems;
G32(pos, numDirItems);
NumDirItems = numDirItems;
if (numDirItems > (1 << 13))
return false;
pos += 4;
if (pos + 8 * NumDirItems > size)
if (pos + 8 * numDirItems > size)
return false;
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);
return true;
}
@ -352,27 +380,41 @@ struct CSection
{
AString Name;
UInt32 ExtractSize;
UInt32 VSize;
UInt32 Va;
UInt32 PSize;
UInt32 Pa;
UInt32 Flags;
UInt32 Time;
// UInt16 NumRelocs;
// UInt16 NumRelocs; // is set to zero for executable images
bool IsRealSect;
bool IsDebug;
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; }
UInt32 GetSizeMin() const { return MyMin(PSize, VSize); }
void Set_Size_for_all(UInt32 size)
{
PSize = VSize = ExtractSize = size;
}
UInt32 GetSize_Extract() const
{
return ExtractSize;
}
void UpdateTotalSize(UInt32 &totalSize) const
{
UInt32 t = Pa + PSize;
const UInt32 t = Pa + PSize;
if (totalSize < t)
totalSize = t;
totalSize = t;
}
void Parse(const Byte *p);
@ -380,8 +422,8 @@ struct CSection
int Compare(const CSection &s) const
{
RINOZ(MyCompare(Pa, s.Pa))
UInt32 size1 = GetSizeExtract();
UInt32 size2 = s.GetSizeExtract();
const UInt32 size1 = GetSize_Extract();
const UInt32 size2 = s.GetSize_Extract();
return MyCompare(size1, size2);
}
};
@ -402,6 +444,10 @@ void CSection::Parse(const Byte *p)
G32(20, Pa);
// G16(32, NumRelocs);
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" },
{ 0x01F0, "PPC" },
{ 0x01F1, "PPC-FP" },
{ 0x01F2, "PPC-BE" },
{ 0x0200, "IA-64" },
{ 0x0266, "MIPS-16" },
{ 0x0284, "Alpha-64" },
@ -830,11 +877,11 @@ enum
kpidStackReserve,
kpidStackCommit,
kpidHeapReserve,
kpidHeapCommit,
kpidImageBase
// kpidAddressOfEntryPoint,
// kpidBaseOfCode,
// kpidBaseOfData32,
kpidHeapCommit
// , kpidImageBase
// , kpidAddressOfEntryPoint
// , kpidBaseOfCode
// , kpidBaseOfData32
};
static const CStatProp kArcProps[] =
@ -864,14 +911,16 @@ static const CStatProp kArcProps[] =
{ "Stack Commit", kpidStackCommit, VT_UI8},
{ "Heap Reserve", kpidHeapReserve, VT_UI8},
{ "Heap Commit", kpidHeapCommit, VT_UI8},
{ "Image Base", kpidImageBase, VT_UI8},
{ NULL, kpidComment, VT_BSTR},
{ NULL, kpidVa, VT_UI8 }, // "Image Base", kpidImageBase, VT_UI8
{ NULL, kpidComment, VT_BSTR}
// { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8},
// { "Base Of Code", kpidBaseOfCode, VT_UI8},
// { "Base Of Data", kpidBaseOfData32, VT_UI8},
// , { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}
// , { "Base Of Code", kpidBaseOfCode, VT_UI8}
// , { "Base Of Data", kpidBaseOfData32, VT_UI8}
};
// #define kpid_NumRelocs 250
static const Byte kProps[] =
{
kpidPath,
@ -880,7 +929,8 @@ static const Byte kProps[] =
kpidVirtualSize,
kpidCharacts,
kpidOffset,
kpidVa,
kpidVa
// , kpid_NumRelocs
};
IMP_IInArchive_Props
@ -899,7 +949,42 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
switch (propID)
{
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:
if (!_versionShortString.IsEmpty())
prop = _versionShortString;
@ -969,8 +1054,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
case kpidStackCommit: prop = _optHeader.StackCommit; break;
case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
case kpidImageBase: prop = _optHeader.ImageBase; break;
case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:
// case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
// case kpidBaseOfCode: prop = _optHeader.BaseOfCode; 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);
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 kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidOffset: prop = item.Pa; break;
@ -1229,7 +1314,7 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
sect.Time = de.Time;
sect.Va = de.Va;
sect.Pa = de.Pa;
sect.PSize = sect.VSize = de.Size;
sect.Set_Size_for_all(de.Size);
}
buf += kEntrySize;
}
@ -1757,7 +1842,7 @@ static void CopyToUString(const Byte *p, UString &s)
{
for (;;)
{
wchar_t c = (wchar_t)Get16(p);
const wchar_t c = (wchar_t)Get16(p);
p += 2;
if (c == 0)
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)
{
unsigned pos = 0;
@ -1783,7 +1878,7 @@ struct CVersionBlock
{
UInt32 TotalLen;
UInt32 ValueLen;
bool IsTextValue;
unsigned IsTextValue;
unsigned StrSize;
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;
bool CVersionBlock::Parse(const Byte *p, UInt32 size)
@ -1812,14 +1924,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
ValueLen = Get16(p + 2);
if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
return false;
switch (Get16(p + 4))
{
case 0: IsTextValue = false; break;
case 1: IsTextValue = true; break;
default: return false;
}
IsTextValue = Get16(p + 4);
if (IsTextValue > 1)
return false;
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)
return false;
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)
size = vb.TotalLen;
size = vb.TotalLen;
CMy_VS_FIXEDFILEINFO FixedFileInfo;
if (!FixedFileInfo.Parse(p + pos))
return false;
@ -1880,7 +1990,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
return false;
if (vb.ValueLen != 0)
return false;
UInt32 endPos = pos + vb.TotalLen;
const UInt32 endPos = pos + vb.TotalLen;
pos += k_ResoureBlockHeader_Size;
f.AddSpaces(2);
@ -1901,7 +2011,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb2;
if (!vb2.Parse(p + pos, endPos - pos))
return false;
UInt32 endPos2 = pos + vb2.TotalLen;
const UInt32 endPos2 = pos + vb2.TotalLen;
if (vb2.IsTextValue)
return false;
pos += k_ResoureBlockHeader_Size;
@ -1919,9 +2029,9 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
UInt32 num = (vb2.ValueLen >> 2);
for (; num != 0; num--, pos += 4)
{
UInt32 dw = Get32(p + pos);
UInt32 lang = LOWORD(dw);
UInt32 codePage = HIWORD(dw);
const UInt32 dw = Get32(p + pos);
const UInt32 lang = LOWORD(dw);
const UInt32 codePage = HIWORD(dw);
f.AddString(", ");
PrintHex(f, lang);
@ -1936,7 +2046,6 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
if (!CompareWStrStrings(p + pos, "StringFileInfo"))
return false;
pos += vb.StrSize + 2;
for (;;)
{
pos += (4 - pos) & 3;
@ -1945,7 +2054,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb2;
if (!vb2.Parse(p + pos, endPos - pos))
return false;
UInt32 endPos2 = pos + vb2.TotalLen;
const UInt32 endPos2 = pos + vb2.TotalLen;
if (vb2.ValueLen != 0)
return false;
pos += k_ResoureBlockHeader_Size;
@ -1967,9 +2076,8 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
CVersionBlock vb3;
if (!vb3.Parse(p + pos, endPos2 - pos))
return false;
// ValueLen sometimes is a number of characters (not bytes)?
// So we don't use it.
UInt32 endPos3 = pos + vb3.TotalLen;
// ValueLen is a number of 16-bit characters (usually it includes zero tail character).
const UInt32 endPos3 = pos + vb3.TotalLen;
pos += k_ResoureBlockHeader_Size;
// 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 += (4 - pos) & 3;
if (vb3.ValueLen > 0 && pos + 2 <= endPos3)
if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)
{
f.AddChar(',');
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)
return false;
/*
if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&
vb3.ValueLen != (unsigned)sLen / 2)
return false;
*/
AddParamString(f, p + pos, (unsigned)sLen);
CopyToUString(p + pos, value);
pos += (unsigned)sLen + 2;
CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);
// pos += (unsigned)sLen + 2;
}
AddToUniqueUStringVector(keys, key, value);
}
pos = endPos3;
f.NewLine();
}
pos = endPos2;
f.CloseBlock(4);
}
}
f.CloseBlock(2);
pos = endPos;
}
f.CloseBlock(0);
@ -2218,7 +2335,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
if (sect2.PSize != 0)
{
sect2.VSize = sect2.PSize;
sect2.ExtractSize = sect2.VSize = sect2.PSize;
sect2.Name = ".rsrc_1";
sect2.Time = 0;
sect2.IsAdditionalSection = true;
@ -2337,6 +2454,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
CSection &sect = _sections.AddNew();
sect.Parse(buffer + pos);
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:
PSize of resource is larger than real size.
@ -2390,7 +2521,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
sect.Name = "CERTIFICATE";
sect.Va = 0;
sect.Pa = certLink.Va;
sect.PSize = sect.VSize = certLink.Size;
sect.Set_Size_for_all(certLink.Size);
sect.UpdateTotalSize(_totalSize);
}
@ -2448,7 +2579,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
sect.Name = "COFF_SYMBOLS";
sect.Va = 0;
sect.Pa = _header.PointerToSymbolTable;
sect.PSize = sect.VSize = size;
sect.Set_Size_for_all(size);
sect.UpdateTotalSize(_totalSize);
}
@ -2464,11 +2595,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
{
CSection &s2 = _sections.AddNew();
s2.Pa = s2.Va = limit;
s2.PSize = s2.VSize = s.Pa - limit;
s2.Set_Size_for_all(s.Pa - limit);
s2.IsAdditionalSection = true;
s2.Name = '[';
s2.Name.Add_Char('[');
s2.Name.Add_UInt32(num++);
s2.Name += ']';
s2.Name.Add_Char(']');
limit = s.Pa;
}
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)
size = _items[mixItem.ResourceIndex].GetSize();
else
size = _sections[mixItem.SectionIndex].GetSizeExtract();
size = _sections[mixItem.SectionIndex].GetSize_Extract();
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;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
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)
for (i = 0;; i++, totalSize += currentItemSize)
{
lps->InSize = lps->OutSize = currentTotalSize;
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur())
if (i >= numItems)
break;
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
@ -2776,15 +2904,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
}
else
{
currentItemSize = sect.GetSizeExtract();
currentItemSize = sect.GetSize_Extract();
if (!testMode && !outStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode))
RINOK(InStream_SeekSet(_stream, sect.Pa))
streamSpec->Init(currentItemSize);
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))
isOk = (copyCoderSpec->TotalSize == currentItemSize);
inStream->Init(currentItemSize);
RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
isOk = (copyCoder->TotalSize == currentItemSize);
}
outStream.Release();
@ -2804,7 +2932,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
const CMixItem &mixItem = _mixItems[index];
const CSection &sect = _sections[mixItem.SectionIndex];
if (mixItem.IsSectionItem())
return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream);
return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);
CBufInStream *inStreamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
@ -2964,7 +3092,7 @@ bool CHeader::Parse(const Byte *p)
G32(12, BaseOfCode);
G64(16, ImageBase);
*/
for (int i = 0; i < 2; i++)
for (unsigned i = 0; i < 2; i++)
{
CDataDir &dd = DataDir[i];
dd.Parse(p + 24 + i * 8);
@ -2997,6 +3125,7 @@ struct CSection
{
Byte Name[NPe::kNameSize];
UInt32 ExtractSize;
UInt32 VSize;
UInt32 Va;
UInt32 PSize;
@ -3013,6 +3142,7 @@ struct CSection
G32(20, Pa);
// G32(p + 32, NumRelocs);
G32(36, Flags);
ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
}
bool Check() const
@ -3022,11 +3152,16 @@ struct CSection
PSize <= ((UInt32)1 << 30);
}
UInt32 GetSize_Extract() const
{
return ExtractSize;
}
void UpdateTotalSize(UInt32 &totalSize)
{
UInt32 t = Pa + PSize;
if (t > totalSize)
totalSize = t;
const UInt32 t = Pa + PSize;
if (totalSize < t)
totalSize = t;
}
};
@ -3050,6 +3185,7 @@ static const Byte kProps[] =
{
kpidPath,
kpidSize,
kpidPackSize,
kpidVirtualSize,
kpidCharacts,
kpidOffset,
@ -3108,7 +3244,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = MultiByteToUnicodeString(name);
break;
}
case kpidSize:
case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
case kpidPackSize: prop = (UInt64)item.PSize; break;
case kpidVirtualSize: prop = (UInt64)item.VSize; break;
case kpidOffset: prop = item.Pa; break;
@ -3168,13 +3304,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
{
COM_TRY_BEGIN
Close();
try
// try
{
if (Open2(inStream) != S_OK)
return S_FALSE;
_stream = inStream;
}
catch(...) { return S_FALSE; }
// catch(...) { return S_FALSE; }
return S_OK;
COM_TRY_END
}
@ -3205,26 +3341,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 totalSize = 0;
UInt32 i;
for (i = 0; i < numItems; i++)
totalSize += _items[allFilesMode ? i : indices[i]].PSize;
extractCallback->SetTotal(totalSize);
totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();
RINOK(extractCallback->SetTotal(totalSize))
UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
lps->Init(extractCallback, false);
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
inStream->SetStream(_stream);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
streamSpec->SetStream(_stream);
totalSize = 0;
for (i = 0; i < numItems; i++)
for (i = 0;; i++)
{
lps->InSize = lps->OutSize = currentTotalSize;
lps->InSize = lps->OutSize = totalSize;
RINOK(lps->SetCur())
if (i >= numItems)
break;
int opRes;
{
CMyComPtr<ISequentialOutStream> realOutStream;
const Int32 askMode = testMode ?
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 CSection &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
currentTotalSize += item.PSize;
const UInt32 size = item.GetSize_Extract();
totalSize += size;
if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode))
int res = NExtract::NOperationResult::kDataError;
RINOK(InStream_SeekSet(_stream, item.Pa))
streamSpec->Init(item.PSize);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress))
if (copyCoderSpec->TotalSize == item.PSize)
res = NExtract::NOperationResult::kOK;
inStream->Init(size);
RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(res))
opRes = (copyCoder->TotalSize == size) ?
NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?
NExtract::NOperationResult::kUnexpectedEnd :
NExtract::NOperationResult::kDataError;
}
RINOK(extractCallback->SetOperationResult(opRes))
}
return S_OK;
COM_TRY_END
@ -3256,7 +3392,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
{
COM_TRY_BEGIN
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
}

View file

@ -11,6 +11,7 @@
#include "../../Common/MyBuffer2.h"
#include "../../Windows/PropVariant.h"
#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamObjects.h"
@ -20,8 +21,8 @@
#include "HandlerCont.h"
#define Get32(p) GetBe32(p)
#define Get64(p) GetBe64(p)
#define Get32(p) GetBe32a(p)
#define Get64(p) GetBe64a(p)
using namespace NWindows;
@ -32,9 +33,9 @@ static const Byte k_Signature[] = { 'Q', 'F', 'I', 0xFB, 0, 0, 0 };
/*
VA to PA maps:
high bits (L1) : : in L1 Table : the reference to L1 Table
mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster
low bits : _clusterBits
high bits (L1) : : index in L1 (_dir) : _dir[high_index] points to Table.
mid bits (L2) : _numMidBits : index in Table, Table[index] points to cluster start offset in arc file.
low bits : _clusterBits : offset inside cluster.
*/
Z7_class_CHandler_final: public CHandlerImg
@ -49,30 +50,27 @@ Z7_class_CHandler_final: public CHandlerImg
CObjArray2<UInt32> _dir;
CAlignedBuffer _table;
UInt64 _cacheCluster;
CByteBuffer _cache;
CByteBuffer _cacheCompressed;
UInt64 _cacheCluster;
UInt64 _comprPos;
size_t _comprSize;
UInt64 _phySize;
CBufInStream *_bufInStreamSpec;
CMyComPtr<ISequentialInStream> _bufInStream;
CBufPtrSeqOutStream *_bufOutStreamSpec;
CMyComPtr<ISequentialOutStream> _bufOutStream;
NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoderSpec;
CMyComPtr<ICompressCoder> _deflateDecoder;
bool _needDeflate;
bool _needCompression;
bool _isArc;
bool _unsupported;
Byte _compressionType;
UInt64 _phySize;
CMyComPtr2<ISequentialInStream, CBufInStream> _bufInStream;
CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> _bufOutStream;
CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> _deflateDecoder;
UInt32 _version;
UInt32 _cryptMethod;
UInt64 _incompatFlags;
HRESULT Seek2(UInt64 offset)
{
@ -96,13 +94,11 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
{
if (processedSize)
*processedSize = 0;
// printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
if (_virtPos >= _size)
return S_OK;
{
UInt64 rem = _size - _virtPos;
const UInt64 rem = _size - _virtPos;
if (size > rem)
size = (UInt32)rem;
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 lowBits = (size_t)_virtPos & (clusterSize - 1);
{
size_t rem = clusterSize - lowBits;
const size_t rem = clusterSize - lowBits;
if (size > rem)
size = (UInt32)rem;
}
if (cluster == _cacheCluster)
{
memcpy(data, _cache + lowBits, size);
@ -130,32 +125,29 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
if (high < _dir.Size())
{
const UInt32 tabl = _dir[(unsigned)high];
const UInt32 tabl = _dir[(size_t)high];
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 Byte *p = (const Byte *)buffer + (midBits << 3);
const Byte *p = _table + ((((size_t)tabl << _numMidBits) + midBits) << 3);
UInt64 v = Get64(p);
if (v != 0)
if (v)
{
if ((v & _compressedFlag) != 0)
if (v & _compressedFlag)
{
if (_version <= 1)
return E_FAIL;
/*
the example of table record for 12-bit clusters (4KB uncompressed).
2 bits : isCompressed status
4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512;
it uses one additional bit over unpacked cluster_bits
49 bits : offset of 512-sector
9 bits : offset in 512-sector
the example of table record for 12-bit clusters (4KB uncompressed):
2 bits : isCompressed status
(4 == _clusterBits - 8) bits : (num_sectors - 1)
packSize = num_sectors * 512;
it uses one additional bit over unpacked cluster_bits.
(49 == 61 - _clusterBits) bits : offset of 512-byte sector
9 bits : offset in 512-byte sector
*/
const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1));
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
const UInt64 offset = v & (((UInt64)1 << 62) - 1);
const size_t dataSize = ((size_t)(offset >> 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 (offset2inCache != 0)
if (offset2inCache)
{
_comprSize -= (size_t)offset2inCache;
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;
size_t dataSize2 = dataSize3;
// 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;
RINOK(hres)
if (dataSize2 != dataSize3)
return E_FAIL;
_comprSize += dataSize2;
}
const size_t kSectorMask = (1 << 9) - 1;
const size_t offsetInSector = ((size_t)offset & kSectorMask);
_bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
const size_t offsetInSector = (size_t)offset & kSectorMask;
_bufInStream->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
_cacheCluster = (UInt64)(Int64)-1;
if (_cache.Size() < clusterSize)
return E_FAIL;
_bufOutStreamSpec->Init(_cache, clusterSize);
_bufOutStream->Init(_cache, clusterSize);
// Do we need to use smaller block than clusterSize for last cluster?
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)
memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
*/
if (res == S_OK)
if (!_deflateDecoderSpec->IsFinished()
|| _bufOutStreamSpec->GetPos() != clusterSize)
if (!_deflateDecoder->IsFinished()
|| _bufOutStream->GetPos() != clusterSize)
res = S_FALSE;
RINOK(res)
_cacheCluster = cluster;
continue;
/*
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)
{
v &= (_compressedFlag - 1);
v &= _compressedFlag - 1;
v += lowBits;
if (v != _posInArc)
{
// printf("\n%12I64x\n", v - _posInArc);
RINOK(Seek2(v))
}
HRESULT res = Stream->Read(data, size, &size);
const HRESULT res = Stream->Read(data, size, &size);
_posInArc += size;
_virtPos += size;
if (processedSize)
@ -274,13 +261,25 @@ static const Byte kProps[] =
static const Byte kArcProps[] =
{
kpidClusterSize,
kpidSectorSize, // actually we need variable to show table size
kpidHeadersSize,
kpidUnpackVer,
kpidMethod
kpidMethod,
kpidCharacts
};
IMP_IInArchive_Props
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))
{
COM_TRY_BEGIN
@ -290,28 +289,54 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
case kpidMainSubfile: prop = (UInt32)0; 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 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:
{
AString s;
if (_needDeflate)
s = "Deflate";
if (_compressionType)
{
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();
if (_cryptMethod == 1)
s += "AES";
if (_cryptMethod == 2)
s += "LUKS";
else
{
s += "Encryption:";
s.Add_UInt32(_cryptMethod);
}
}
if (!s.IsEmpty())
prop = s;
break;
}
@ -321,9 +346,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
// if (_headerError) v |= kpv_ErrorFlags_HeadersError;
if (!Stream && v == 0 && _isArc)
if (!Stream && v == 0)
v = kpv_ErrorFlags_HeadersError;
if (v != 0)
if (v)
prop = v;
break;
}
@ -355,76 +380,91 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
{
const unsigned kHeaderSize = 18 * 4;
Byte buf[kHeaderSize];
RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))
if (memcmp(buf, k_Signature, 4) != 0)
UInt64 buf64[0x70 / 8];
RINOK(ReadStream_FALSE(stream, buf64, sizeof(buf64)))
const void *buf = (const void *)buf64;
// signature: { 'Q', 'F', 'I', 0xFB }
if (*(const UInt32 *)buf != Z7_CONV_BE_TO_NATIVE_CONST32(0x514649fb))
return S_FALSE;
_version = Get32(buf + 4);
_version = Get32((const Byte *)(const void *)buf64 + 4);
if (_version < 1 || _version > 3)
return S_FALSE;
const UInt64 backOffset = Get64(buf + 8);
// UInt32 backSize = Get32(buf + 0x10);
const UInt64 k_UncompressedSize_MAX = (UInt64)1 << 60;
const UInt64 k_CompressedSize_MAX = (UInt64)1 << 60;
UInt64 l1Offset;
UInt32 l1Size;
_size = Get64((const Byte *)(const void *)buf64 + 0x18);
if (_size > k_UncompressedSize_MAX)
return S_FALSE;
size_t l1Size;
UInt32 headerSize;
if (_version == 1)
{
// _mTime = Get32(buf + 0x14); // is unused im most images
_size = Get64(buf + 0x18);
_clusterBits = buf[0x20];
_numMidBits = buf[0x21];
// _mTime = Get32((const Byte *)(const void *)buf64 + 0x14); // is unused in most images
_clusterBits = ((const Byte *)(const void *)buf64)[0x20];
_numMidBits = ((const Byte *)(const void *)buf64)[0x21];
if (_clusterBits < 9 || _clusterBits > 30)
return S_FALSE;
if (_numMidBits < 1 || _numMidBits > 28)
return S_FALSE;
_cryptMethod = Get32(buf + 0x24);
l1Offset = Get64(buf + 0x28);
if (l1Offset < 0x30)
return S_FALSE;
const unsigned numBits2 = (_clusterBits + _numMidBits);
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x24);
const unsigned numBits2 = _clusterBits + _numMidBits;
const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
if (l1Size64 > ((UInt32)1 << 31))
return S_FALSE;
l1Size = (UInt32)l1Size64;
l1Size = (size_t)l1Size64;
headerSize = 0x30;
}
else
{
_clusterBits = Get32(buf + 0x14);
_clusterBits = Get32((const Byte *)(const void *)buf64 + 0x14);
if (_clusterBits < 9 || _clusterBits > 30)
return S_FALSE;
_numMidBits = _clusterBits - 3;
_size = Get64(buf + 0x18);
_cryptMethod = Get32(buf + 0x20);
l1Size = Get32(buf + 0x24);
l1Offset = Get64(buf + 0x28); // must be aligned for cluster
_cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x20);
l1Size = Get32((const Byte *)(const void *)buf64 + 0x24);
headerSize = 0x48;
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 UInt32 refClusters = Get32(buf + 0x38);
// UInt32 numSnapshots = Get32(buf + 0x3C);
// UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster
const UInt64 refOffset = Get64((const Byte *)(const void *)buf64 + 0x30); // must be aligned for cluster
const UInt32 refClusters = Get32((const Byte *)(const void *)buf64 + 0x38);
// UInt32 numSnapshots = Get32((const Byte *)(const void *)buf64 + 0x3C);
// UInt64 snapshotsOffset = Get64((const Byte *)(const void *)buf64 + 0x40); // must be aligned for cluster
/*
if (numSnapshots != 0)
if (numSnapshots)
return S_FALSE;
*/
if (refClusters != 0)
if (refClusters)
{
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;
refs.Alloc(numBytes);
RINOK(InStream_SeekSet(stream, refOffset))
RINOK(ReadStream_FALSE(stream, refs, numBytes));
*/
const UInt64 end = refOffset + numBytes;
if (_phySize < end)
_phySize = end;
_phySize = end;
/*
for (size_t i = 0; i < numBytes; i += 2)
{
@ -436,48 +476,76 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
}
}
_isArc = true;
if (backOffset != 0)
{
_unsupported = true;
const UInt64 l1Offset = Get64((const Byte *)(const void *)buf64 + 0x28); // must be aligned for cluster ?
if (l1Offset < headerSize || l1Offset > k_CompressedSize_MAX)
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;
CByteBuffer table;
const size_t t1SizeBytes = (size_t)l1Size << 3;
{
const size_t t1SizeBytes = (size_t)l1Size << 3;
if ((t1SizeBytes >> 3) != l1Size)
const UInt64 end = l1Offset + t1SizeBytes;
if (end > k_CompressedSize_MAX)
return S_FALSE;
table.Alloc(t1SizeBytes);
RINOK(InStream_SeekSet(stream, l1Offset))
RINOK(ReadStream_FALSE(stream, table, t1SizeBytes))
{
UInt64 end = l1Offset + t1SizeBytes;
// we need to uses align end for empty qcow files
end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
if (_phySize < end)
// we need to use align end for empty qcow files
// some files has no cluster alignment padding at the end
// but has sector alignment
// end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
if (_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);
const UInt64 offsetMask = _compressedFlag - 1;
UInt32 numTables = 0;
UInt32 i;
const size_t midSize = (size_t)1 << (_numMidBits + 3);
size_t numTables = 0;
size_t i;
for (i = 0; i < l1Size; i++)
{
const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask;
if (v != 0)
numTables++;
const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
if (!v)
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);
if (size >> (_numMidBits + 3) != numTables)
@ -485,48 +553,38 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
_table.Alloc(size);
if (!_table.IsAllocated())
return E_OUTOFMEMORY;
if (openCallback)
{
const UInt64 totalBytes = size;
RINOK(openCallback->SetTotal(NULL, &totalBytes))
}
}
_dir.SetSize(l1Size);
_dir.SetSize((unsigned)l1Size);
UInt32 curTable = 0;
if (openCallback)
{
const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3);
RINOK(openCallback->SetTotal(NULL, &totalBytes))
}
for (i = 0; i < l1Size; i++)
{
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)
{
_dir[i] = kEmptyDirItem;
continue;
}
_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;
curTable++;
if (openCallback && (tableOffset & 0xFFFFF) == 0)
{
const UInt64 numBytes = tableOffset;
RINOK(openCallback->SetCompleted(NULL, &numBytes))
}
RINOK(InStream_SeekSet(stream, v))
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)
@ -537,33 +595,30 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
UInt64 offset = v & offsetMask;
size_t dataSize = clusterSize;
if ((v & _compressedFlag) != 0)
if (v & _compressedFlag)
{
if (_version <= 1)
{
unsigned numOffsetBits = (63 - _clusterBits);
const unsigned numOffsetBits = 63 - _clusterBits;
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
offset &= ((UInt64)1 << numOffsetBits) - 1;
dataSize = 0;
// offset >>= 9;
// offset <<= 9;
dataSize = 0; // why ?
// offset &= ~(((UInt64)1 << 9) - 1);
}
else
{
unsigned numOffsetBits = (62 - (_clusterBits - 8));
const unsigned numOffsetBits = 62 - (_clusterBits - 8);
dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
offset &= ((UInt64)1 << numOffsetBits) - 1;
offset >>= 9;
offset <<= 9;
offset &= ((UInt64)1 << numOffsetBits) - (1 << 9);
}
_needDeflate = true;
_needCompression = true;
}
else
{
UInt32 low = (UInt32)v & 511;
if (low != 0)
const UInt32 low = (UInt32)v & 511;
if (low)
{
// version 3 support zero clusters
// version_3 supports zero clusters
if (_version < 3 || low != 1)
{
_unsupported = true;
@ -574,17 +629,18 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
const UInt64 end = offset + dataSize;
if (_phySize < end)
_phySize = end;
_phySize = end;
}
}
if (curTable != numTables)
return E_FAIL;
if (_cryptMethod != 0)
if (_cryptMethod)
_unsupported = true;
if (_needDeflate && _version <= 1) // that case was not implemented
if (_needCompression && _version <= 1) // that case was not implemented
_unsupported = true;
if (_compressionType)
_unsupported = true;
Stream = stream;
@ -596,16 +652,21 @@ Z7_COM7F_IMF(CHandler::Close())
{
_table.Free();
_dir.Free();
// _cache.Free();
// _cacheCompressed.Free();
_phySize = 0;
_cacheCluster = (UInt64)(Int64)-1;
_comprPos = 0;
_comprSize = 0;
_needDeflate = false;
_needCompression = false;
_isArc = false;
_unsupported = false;
_compressionType = 0;
_incompatFlags = 0;
// CHandlerImg:
Clear_HandlerImg_Vars();
Stream.Release();
@ -617,39 +678,20 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
{
COM_TRY_BEGIN
*stream = NULL;
if (_unsupported)
if (_unsupported || !Stream)
return S_FALSE;
if (_needDeflate)
if (_needCompression)
{
if (_version <= 1)
if (_version <= 1 || _compressionType)
return S_FALSE;
if (!_bufInStream)
{
_bufInStreamSpec = new CBufInStream;
_bufInStream = _bufInStreamSpec;
}
if (!_bufOutStream)
{
_bufOutStreamSpec = new CBufPtrSeqOutStream();
_bufOutStream = _bufOutStreamSpec;
}
if (!_deflateDecoder)
{
_deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
_deflateDecoder = _deflateDecoderSpec;
_deflateDecoderSpec->Set_NeedFinishInput(true);
}
_bufInStream.Create_if_Empty();
_bufOutStream.Create_if_Empty();
_deflateDecoder.Create_if_Empty();
_deflateDecoder->Set_NeedFinishInput(true);
const size_t clusterSize = (size_t)1 << _clusterBits;
_cache.AllocAtLeast(clusterSize);
_cacheCompressed.AllocAtLeast(clusterSize * 2);
}
CMyComPtr<ISequentialInStream> streamTemp = this;
RINOK(InitAndSeek())
*stream = streamTemp.Detach();

View file

@ -1456,7 +1456,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
}
if (arcInfo->Locator.Is_Recovery())
{
s += "Recovery:";
s.Add_OptSpaced("Recovery:");
s.Add_UInt64(arcInfo->Locator.Recovery);
}
}

View file

@ -1755,16 +1755,17 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
if (_hres != S_OK)
return _hres;
if (size == 0 || _cachedSize == 0)
if (size > _cachedSize)
size = _cachedSize;
// (size <= _cachedSize)
if (size == 0)
return S_OK;
RINOK(SeekPhy(_cachedPos))
for (;;)
{
// (_phyPos == _cachedPos)
const size_t pos = (size_t)_cachedPos & kCacheMask;
size_t cur = kCacheSize - pos;
cur = MyMin(cur, _cachedSize);
cur = MyMin(cur, size);
const size_t cur = MyMin(kCacheSize - pos, size);
_hres = SetRestriction_ForWrite(cur);
RINOK(_hres)
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;
_cachedSize -= cur;
size -= cur;
if (size == 0 || _cachedSize == 0)
if (size == 0)
return S_OK;
}
}
@ -1964,7 +1965,11 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
// so we reduce cache
_cachedSize = (size_t)offset;
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)
// so we must reduce phyStream size to (newSize) or to (_cachedPos)
// newPhySize = _cachedPos; // optional reduce to _cachedPos

View file

@ -3713,7 +3713,7 @@ HRESULT Bench(
}
*/
bool ramSize_Defined = NSystem::GetRamSize(ramSize);
const bool ramSize_Defined = NSystem::GetRamSize(ramSize);
UInt32 numThreadsSpecified = numCPUs;
bool needSetComplexity = false;
@ -4002,16 +4002,29 @@ HRESULT Bench(
}
}
if (numThreadsSpecified >= 2)
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)
printCallback->NewLine();
/* it can show incorrect frequency for HT threads.
so we reduce freq test to (numCPUs / 2) */
/* it can show incorrect frequency for HT threads. */
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)
numThreads = 1;

View file

@ -21,8 +21,8 @@
using namespace NWindows;
static const unsigned kNumWinAtrribFlags = 21;
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU";
static const unsigned kNumWinAtrribFlags = 30;
static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B";
/*
FILE_ATTRIBUTE_
@ -48,8 +48,9 @@ FILE_ATTRIBUTE_
18 RECALL_ON_OPEN or EA
19 PINNED
20 UNPINNED
21 STRICTLY_SEQUENTIAL
21 STRICTLY_SEQUENTIAL (10.0.16267)
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++)
{
UInt32 flag = (1 << i);
if ((wa & flag) != 0)
const UInt32 flag = (UInt32)1 << i;
if (wa & flag)
{
char c = g_WinAttribChars[i];
const char c = g_WinAttribChars[i];
if (c != '.')
{
wa &= ~flag;

View file

@ -1606,7 +1606,23 @@ HRESULT UpdateArchive(
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));
return errorInfo.Get_HRESULT_Error();
}

View file

@ -924,11 +924,11 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
}
else
{
NumArcsWithError++;
// we don't update NumArcsWithError, if error is not related to archive data.
if (result == E_ABORT
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
)
|| result == HRESULT_FROM_WIN32(ERROR_DISK_FULL))
return result;
NumArcsWithError++;
if (_se)
{

View file

@ -534,7 +534,8 @@ 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();
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 finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1));
}

View file

@ -387,8 +387,8 @@ Z7_COM7F_IMF(CAltStreamsFolder::WasChanged(Int32 *wasChanged))
return S_OK;
}
DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
const DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
const bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
if (wasChangedLoc)
{
_findChangeNotification.FindNext();
@ -666,16 +666,10 @@ Z7_COM7F_IMF(CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID
Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
{
const CAltStream &ss = Streams[index];
*iconIndex = 0;
int iconIndexTemp;
if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
0 // fi.Attrib
, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return GetLastError_noZero_HRESULT();
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
_pathPrefix + us2fs(ss.Name),
FILE_ATTRIBUTE_ARCHIVE,
iconIndex);
}
/*

View file

@ -782,6 +782,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex)
if (useSrcPanel)
{
CCopyToOptions options;
// options.src_Is_IO_FS_Folder = useFullItemPaths;
options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
options.moveMode = move;
options.includeAltStreams = true;

View file

@ -208,8 +208,8 @@ bool CBrowseDialog::OnInit()
_filterCombo.SetCurSel(FilterIndex);
}
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
_list.InsertColumn(0, LangString(IDS_PROP_NAME), 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
if (isDrive)
{
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
item.iImage = 0;
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
fi.Name + FCHAR_PATH_SEPARATOR,
FILE_ATTRIBUTE_DIRECTORY);
}
else
#endif
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
if (item.iImage < 0)
item.iImage = 0;
item.iImage = 0;
_list.InsertItem(&item);
wchar_t s[64];
{
s[0] = 0;
ConvertUtcFileTimeToString(fi.MTime, s,
if (!FILETIME_IsZero(fi.MTime))
ConvertUtcFileTimeToString(fi.MTime, s,
#ifndef UNDER_CE
kTimestampPrintLevel_MIN
#else

View file

@ -356,8 +356,8 @@ bool CBrowseDialog2::OnInit()
#endif
}
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
_list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
unsigned columnIndex = 0;
_list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
@ -1639,15 +1639,15 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
#ifndef UNDER_CE
if (isDrive)
{
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
item.iImage = 0;
item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
fi.Name + FCHAR_PATH_SEPARATOR,
FILE_ATTRIBUTE_DIRECTORY);
}
else
#endif
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
if (item.iImage < 0)
item.iImage = 0;
item.iImage = 0;
_list.InsertItem(&item);
wchar_t s[64];
{
@ -1662,7 +1662,6 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
);
_list.SetSubItem(index, subItem++, s);
}
{
s[0] = 0;
Browse_ConvertSizeToString(bi, s);

View file

@ -206,13 +206,15 @@ Z7_COM7F_IMF(CExtractCallbackImp::AskOverwrite(
{
COverwriteDialog dialog;
dialog.OldFileInfo.SetTime(existTime);
dialog.OldFileInfo.SetSize(existSize);
dialog.OldFileInfo.Name = existName;
dialog.OldFileInfo.SetTime2(existTime);
dialog.OldFileInfo.SetSize2(existSize);
dialog.OldFileInfo.Path = existName;
dialog.OldFileInfo.Is_FileSystemFile = true;
dialog.NewFileInfo.SetTime(newTime);
dialog.NewFileInfo.SetSize(newSize);
dialog.NewFileInfo.Name = newName;
dialog.NewFileInfo.SetTime2(newTime);
dialog.NewFileInfo.SetSize2(newSize);
dialog.NewFileInfo.Path = newName;
dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder;
ProgressDialog->WaitCreating();
INT_PTR writeAnswer = dialog.Create(*ProgressDialog);

View file

@ -224,6 +224,8 @@ public:
bool ProcessAltStreams;
bool StreamMode;
bool ThereAreMessageErrors;
bool Src_Is_IO_FS_Folder;
#ifndef Z7_NO_CRYPTO
bool PasswordIsDefined;
bool PasswordWasAsked;
@ -286,6 +288,8 @@ public:
, MultiArcMode(false)
, ProcessAltStreams(true)
, StreamMode(false)
, ThereAreMessageErrors(false)
, Src_Is_IO_FS_Folder(false)
#ifndef Z7_NO_CRYPTO
, PasswordIsDefined(false)
, PasswordWasAsked(false)

View file

@ -45,7 +45,8 @@ struct CPhysTempBuffer
~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)
{
NIO::CInFile inFile;
@ -74,9 +75,11 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
for (UInt64 pos = 0; pos < fileSize;)
{
UInt64 progressCur = progressStart + pos;
RINOK(progress->SetCompleted(&progressCur))
UInt64 rem = fileSize - pos;
{
const UInt64 progressCur = progressStart + pos;
RINOK(progress->SetCompleted(&progressCur))
}
const UInt64 rem = fileSize - pos;
UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
UInt32 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)
return E_FAIL;
}
if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
return GetLastError_noZero_HRESULT();
if (curSize != processedSize)
@ -135,9 +137,7 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
FOR_VECTOR (i, driveStrings)
{
CDriveInfo di;
const FString &driveName = driveStrings[i];
di.FullSystemName = driveName;
if (!driveName.IsEmpty())
di.Name.SetFrom(driveName, driveName.Len() - 1);
@ -183,25 +183,24 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
{
FString name ("PhysicalDrive");
name.Add_UInt32(n);
FString fullPath (kVolPrefix);
fullPath += name;
CFileInfo fi;
if (!fi.Find(fullPath))
continue;
CDriveInfo di;
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.DriveSize = fi.Size;
di.FreeSpace = 0;
di.DriveType = 0;
di.IsPhysicalDrive = true;
di.KnownSize = true;
_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))
{
if (itemIndex >= (UInt32)_drives.Size())
if (itemIndex >= _drives.Size())
return E_INVALIDARG;
NCOM::CPropVariant prop;
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))
{
*resultFolder = NULL;
if (index >= (UInt32)_drives.Size())
if (index >= _drives.Size())
return E_INVALIDARG;
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))
{
*iconIndex = 0;
*iconIndex = -1;
const CDriveInfo &di = _drives[index];
if (di.IsPhysicalDrive)
return S_OK;
int iconIndexTemp;
if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return GetLastError_noZero_HRESULT();
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
di.FullSystemName,
_volumeMode ?
FILE_ATTRIBUTE_ARCHIVE:
FILE_ATTRIBUTE_DIRECTORY,
iconIndex);
}
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)
return S_OK;
if (moveMode)
return E_NOTIMPL;
if (!_volumeMode)
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->SetNumFiles(numItems))
FString destPath = us2fs(path);
const FString destPath = us2fs(path);
if (destPath.IsEmpty())
return E_INVALIDARG;
bool isAltDest = NName::IsAltPathPrefix(destPath);
bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
const bool isAltDest = NName::IsAltPathPrefix(destPath);
const bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
if (isDirectPath)
{
@ -428,7 +422,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
RINOK(callback->SetCompleted(&completedSize))
for (i = 0; i < numItems; i++)
{
unsigned index = indices[i];
const unsigned index = indices[i];
const CDriveInfo &di = _drives[index];
FString destPath2 = destPath;
@ -443,7 +437,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
destPath2 += destName;
}
FString srcPath = di.GetDeviceFileIoName();
const FString srcPath = di.GetDeviceFileIoName();
UInt64 fileSize = 0;
if (GetFileSize(index, fileSize) != S_OK)

View file

@ -535,7 +535,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
{
NCOM::CPropVariant prop;
/*
if (index >= (UInt32)Files.Size())
if (index >= Files.Size())
{
CAltStream &ss = Streams[index - Files.Size()];
CDirItem &fi = Files[ss.Parent];
@ -561,7 +561,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
case kpidComment: break;
default: index = ss.Parent;
}
if (index >= (UInt32)Files.Size())
if (index >= Files.Size())
{
prop.Detach(value);
return S_OK;
@ -716,8 +716,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI
/*
const CAltStream *ss1 = NULL;
const CAltStream *ss2 = NULL;
if (index1 >= (UInt32)Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
if (index2 >= (UInt32)Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
if (index1 >= Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
if (index2 >= Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
*/
CDirItem &fi1 = Files[index1];
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))
{
if (index >= (UInt32)Files.Size())
if (index >= Files.Size())
return S_OK;
CDirItem &fi = Files[index];
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 */))
{
if (index >= (UInt32)Files.Size())
if (index >= Files.Size())
return E_NOTIMPL;
const CDirItem &fi = Files[index];
// FString prefix;
@ -1103,9 +1103,9 @@ Z7_COM7F_IMF(CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress
UInt32 index = indices[i];
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)
{
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,
const PROPVARIANT *value, IProgress * /* progress */))
{
if (index >= (UInt32)Files.Size())
if (index >= Files.Size())
return E_INVALIDARG;
CDirItem &fi = Files[index];
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))
{
if (index >= (UInt32)Files.Size())
*iconIndex = -1;
if (index >= Files.Size())
return E_INVALIDARG;
const CDirItem &fi = Files[index];
*iconIndex = 0;
int iconIndexTemp;
if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0)
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return GetLastError_noZero_HRESULT();
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
_path + GetRelPath(fi), fi.Attrib, iconIndex);
}
Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode))

View file

@ -22,11 +22,11 @@ class CFSFolder;
struct CDirItem: public NWindows::NFile::NFind::CFileInfo
{
#ifndef UNDER_CE
#ifndef UNDER_CE
UInt64 PackSize;
#endif
#endif
#ifdef FS_SHOW_LINKS_INFO
#ifdef FS_SHOW_LINKS_INFO
FILETIME ChangeTime;
UInt64 FileIndex;
UInt32 NumLinks;
@ -34,22 +34,21 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfo
bool FileInfo_WasRequested;
bool ChangeTime_Defined;
bool ChangeTime_WasRequested;
#endif
#endif
#ifndef UNDER_CE
#ifndef UNDER_CE
bool PackSize_Defined;
#endif
#endif
bool FolderStat_Defined;
int Parent;
#ifndef UNDER_CE
#ifndef UNDER_CE
CByteBuffer Reparse;
#endif
#endif
UInt64 NumFolders;
UInt64 NumFiles;
int Parent;
};
/*
@ -126,20 +125,18 @@ class CFSFolder Z7_final:
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
// Z7_IFACE_COM7_IMP(IFolderSetShowNtfsStreamsMode)
private:
FString _path;
bool _flatMode;
bool _commentsAreLoaded;
// bool _scanAltStreams;
FString _path;
CObjectVector<CDirItem> Files;
FStringVector Folders;
// CObjectVector<CAltStream> Streams;
// CMyComPtr<IFolderFolder> _parentFolder;
bool _commentsAreLoaded;
CPairsStorage _comments;
// bool _scanAltStreams;
bool _flatMode;
#ifdef _WIN32
NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
#endif
@ -163,9 +160,11 @@ public:
HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
#endif
CFSFolder() : _flatMode(false)
CFSFolder():
_flatMode(false),
_commentsAreLoaded(false)
// , _scanAltStreams(false)
{}
{}
void GetFullPath(const CDirItem &item, FString &path) const
{

View file

@ -515,8 +515,22 @@ static HRESULT CopyFile_Ask(
RINOK(state.ProgressInfo.ProgressResult)
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.
RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew))
RINOK(SendMessageError(state.Callback, errorMessage, destPathNew))
return E_ABORT;
}
state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;

View file

@ -254,28 +254,23 @@ Z7_COM7F_IMF(CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value))
Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
{
if (index >= (UInt32)_items.Size())
*iconIndex = -1;
if (index >= _items.Size())
return E_INVALIDARG;
*iconIndex = 0;
const CResourceW &resource = _items[index];
int iconIndexTemp;
if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
resource.Usage == RESOURCEUSAGE_CONNECTABLE)
{
if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp))
{
*iconIndex = iconIndexTemp;
return S_OK;
}
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
us2fs(resource.RemoteName), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
}
else
{
if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp))
{
*iconIndex = iconIndexTemp;
return S_OK;
}
// *anIconIndex = GetRealIconIndex(0, L"\\\\HOME");
#if 0
return S_FALSE;
#else
return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
FTEXT("__DIR__"), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
#endif
}
return GetLastError_noZero_HRESULT();
}

View file

@ -2,8 +2,10 @@
#include "StdAfx.h"
#include "../../../Common/IntToString.h"
#include "../../../Common/StringConvert.h"
#include "../../../Windows/FileFind.h"
#include "../../../Windows/PropVariantConv.h"
#include "../../../Windows/ResourceString.h"
@ -29,12 +31,16 @@ static const UInt32 kLangIDs[] =
};
#endif
static const unsigned kCurrentFileNameSizeLimit = 82;
static const unsigned kCurrentFileNameSizeLimit2 = 30;
static const unsigned kCurrentFileNameSizeLimit = 72;
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)
{
s.Delete(size / 2, s.Len() - size);
@ -42,66 +48,201 @@ void COverwriteDialog::ReduceString(UString &s)
}
if (!s.IsEmpty() && s.Back() == ' ')
{
// s += (wchar_t)(0x2423);
// s += (wchar_t)(0x2423); // visible space
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;
if (fileInfo.SizeIsDefined)
sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
NControl::CStatic staticContol;
staticContol.Attach(GetItem(iconID));
hIcon = staticContol.SetIcon(hIcon);
if (hIcon)
DestroyIcon(hIcon);
}
const UString &fileName = fileInfo.Name;
int slashPos = fileName.ReverseFind_PathSepar();
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)
void AddSizeValue(UString &s, UInt64 value);
void AddSizeValue(UString &s, UInt64 value)
{
{
AddLangString(s, IDS_PROP_MTIME);
s += ": ";
char t[64];
ConvertUtcFileTimeToString(fileInfo.Time, t);
s += t;
wchar_t sz[32];
ConvertUInt64ToString(value, sz);
s += MyFormatNew(IDS_FILE_SIZE, sz);
}
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))
if (value >= (1 << 10))
{
NControl::CStatic staticContol;
staticContol.Attach(GetItem(iconID));
staticContol.SetIcon(shellFileInfo.hIcon);
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.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()
{
#ifdef Z7_LANG
LangSetWindowText(*this, IDD_OVERWRITE);
LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
#endif
SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo);
SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo);
SetFileInfoControl(OldFileInfo,
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();
if (!ShowExtraButtons)
@ -122,6 +263,15 @@ bool COverwriteDialog::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)
{
switch (buttonID)

View file

@ -12,68 +12,78 @@ namespace NOverwriteDialog
{
struct CFileInfo
{
bool SizeIsDefined;
bool TimeIsDefined;
bool Size_IsDefined;
bool Time_IsDefined;
bool Is_FileSystemFile;
UInt64 Size;
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)
TimeIsDefined = false;
Time_IsDefined = false;
else
{
TimeIsDefined = true;
Time = *t;
}
SetTime(*t);
}
void SetSize(UInt64 size)
{
SizeIsDefined = true;
Size = size;
Size_IsDefined = true;
}
void SetSize(const UInt64 *size)
void SetSize2(const UInt64 *size)
{
if (!size)
SizeIsDefined = false;
Size_IsDefined = false;
else
SetSize(*size);
}
CFileInfo():
Size_IsDefined(false),
Time_IsDefined(false),
Is_FileSystemFile(false)
{}
};
}
class COverwriteDialog: public NWindows::NControl::CModalDialog
{
#ifdef UNDER_CE
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 OnDestroy() Z7_override;
virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
void ReduceString(UString &s);
public:
bool ShowExtraButtons;
bool DefaultButton_is_NO;
NOverwriteDialog::CFileInfo OldFileInfo;
NOverwriteDialog::CFileInfo NewFileInfo;
COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}
INT_PTR Create(HWND parent = NULL)
{
#ifdef UNDER_CE
BIG_DIALOG_SIZE(280, 200);
#ifdef UNDER_CE
_isBig = isBig;
#else
_isBig = true;
#endif
#endif
return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
}
NOverwriteDialog::CFileInfo OldFileInfo;
NOverwriteDialog::CFileInfo NewFileInfo;
};
#endif

View file

@ -1,7 +1,7 @@
#include "OverwriteDialogRes.h"
#include "../../GuiCommon.rc"
#define xc 280
#define xc 340
#define yc 200
#undef iconSize
@ -25,11 +25,13 @@ BEGIN
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_2, m, 44 + iconSize, iconSize, iconSize
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
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
PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys

View file

@ -11,7 +11,9 @@
#define IDB_NO_TO_ALL 441
#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_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

View file

@ -420,8 +420,8 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
_listView._panel = this;
_listView.SetWindowProc();
_listView.SetImageList(GetSysImageList(true), LVSIL_SMALL);
_listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
_listView.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
_listView.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
// _exStyle |= LVS_EX_HEADERDRAGDROP;
// DWORD extendedStyle = _listView.GetExtendedListViewStyle();
@ -506,17 +506,15 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
#endif
, NULL,
WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
0, 0, 100, 520,
0, 0, 100, 620,
(_headerReBar ? _headerToolBar : (HWND)*this),
(HMENU)(UINT_PTR)(_comboBoxID),
g_hInstance, NULL);
#ifndef UNDER_CE
#ifndef UNDER_CE
_headerComboBox.SetUnicodeFormat(true);
_headerComboBox.SetImageList(GetSysImageList(true));
_headerComboBox.SetImageList(Shell_Get_SysImageList_smallIcons(true));
_headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
/*
_headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
_headerComboBox._panel = this;
@ -525,9 +523,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
LONG_PTR(ComboBoxSubclassProc));
*/
_comboBoxEdit.Attach(_headerComboBox.GetEditControl());
// _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
_comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
_comboBoxEdit._panel = this;
#ifndef _UNICODE
@ -538,8 +534,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
#endif
_comboBoxEdit._origWindowProc =
(WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
#endif
#endif
if (_headerReBar)
{

View file

@ -147,11 +147,11 @@ public:
struct CTempFileInfo
{
UInt32 FileIndex; // index of file in folder
bool NeedDelete;
UString RelPath; // Relative path of file from Folder
FString FolderPath;
FString FilePath;
NWindows::NFile::NFind::CFileInfo FileInfo;
bool NeedDelete;
CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {}
void DeleteDirAndFile() const
@ -171,15 +171,15 @@ struct CTempFileInfo
struct CFolderLink: public CTempFileInfo
{
bool IsVirtual;
bool UsePassword;
NWindows::NDLL::CLibrary Library;
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)
bool UsePassword;
UString Password;
bool IsVirtual;
UString VirtualPath; // without tail slash
CFolderLink(): UsePassword(false), IsVirtual(false) {}
CFolderLink(): IsVirtual(false), UsePassword(false) {}
bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
{
@ -310,7 +310,7 @@ struct COpenResult
class CPanel Z7_final: public NWindows::NControl::CWindow2
{
CExtToIconMap _extToIconMap;
// CExtToIconMap _extToIconMap;
UINT _baseID;
unsigned _comboBoxID;
UINT _statusBarID;
@ -324,7 +324,7 @@ class CPanel Z7_final: public NWindows::NControl::CWindow2
virtual void OnDestroy() 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);
@ -355,7 +355,7 @@ public:
HWND _mainWindow;
CPanelCallback *_panelCallback;
void SysIconsWereChanged() { _extToIconMap.Clear(); }
// void SysIconsWereChanged() { _extToIconMap.Clear(); }
void DeleteItems(bool toRecycleBin);
void CreateFolder();

View file

@ -189,7 +189,9 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options,
extracter.ExtractCallbackSpec = new CExtractCallbackImp;
extracter.ExtractCallback = extracter.ExtractCallbackSpec;
extracter.ExtractCallbackSpec->Src_Is_IO_FS_Folder =
IsFSFolder() || IsAltStreamsFolder();
// options.src_Is_IO_FS_Folder;
extracter.options = &options;
extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
extracter.CompressingMode = false;

View file

@ -368,14 +368,41 @@ void CPanel::LoadFullPath()
_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;
if (GetRealIconIndex(path, attributes, index) != 0)
return index;
return -1;
if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(path, attrib, index))
if (index >= 0)
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()
{
LoadFullPath();
@ -387,30 +414,97 @@ void CPanel::LoadFullPathAndShow()
COMBOBOXEXITEM item;
item.mask = 0;
item.iImage = -1;
UString path = _currentFolderPrefix;
if (path.Len() >
#ifdef _WIN32
3
#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
// path = "\\\\.\\PhysicalDrive1\\"; // for debug
// path = "\\\\.\\y:\\"; // for debug
if (!path.IsEmpty())
{
CFileInfo fi;
if (fi.Find(us2fs(path)))
attrib = fi.Attrib;
}
item.iImage = GetRealIconIndex(us2fs(path), attrib);
const unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
if (rootPrefixSize == 0 && path[0] != '\\')
{
int iconIndex = -1;
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)
{
item.iSelectedImage = item.iImage;
@ -495,13 +589,13 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
}
#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
UString s;
iconIndex = iconIndex;
for (int i = 0; i < indent; i++)
for (unsigned i = 0; i < indent; i++)
s += " ";
_headerComboBox.AddString(s + name);
@ -509,23 +603,26 @@ void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, boo
COMBOBOXEXITEMW item;
item.mask = CBEIF_TEXT | CBEIF_INDENT;
if (iconIndex < 0)
iconIndex = g_Ext_to_Icon_Map.GetIconIndex_DIR();
item.iSelectedImage = item.iImage = iconIndex;
if (iconIndex >= 0)
item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
item.iItem = -1;
item.iIndent = indent;
item.iIndent = (int)indent;
item.pszText = name.Ptr_non_const();
_headerComboBox.InsertItem(&item);
#endif
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)
{
@ -537,56 +634,168 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
ComboBoxPaths.Clear();
_headerComboBox.ResetContent();
unsigned i;
UString sumPath;
UStringVector pathParts;
SplitPathToParts(_currentFolderPrefix, pathParts);
UString sumPass;
if (!pathParts.IsEmpty())
pathParts.DeleteBack();
for (i = 0; i < pathParts.Size(); i++)
unsigned indent = 0;
{
const UString name = pathParts[i];
sumPass += name;
sumPass.Add_PathSepar();
CFileInfo info;
DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
if (info.Find(us2fs(sumPass)))
attrib = info.Attrib;
AddComboBoxItem(
name.IsEmpty() ? L"\\" : name,
GetRealIconIndex(us2fs(sumPass), attrib),
(int)i, // iIndent
UString path = _currentFolderPrefix;
// path = L"\\\\.\\y:\\"; // for debug
UString prefix0;
if (path.IsPrefixedBy_Ascii_NoCase("\\\\"))
{
const int separ = FindCharPosInString(path.Ptr(2), '\\');
if (separ > 0
&& (separ > 1 || path[2] != '.')) // "\\\\.\\" will be processed later
{
const UString s = path.Left(2 + separ);
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
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];
ComboBoxPaths.Add(fs2us(s));
int iconIndex2 = GetRealIconIndex(s, 0);
if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR)
s.DeleteBack();
AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
int iconIndex;
const UString name = RootFolder_GetName_Documents(iconIndex);
// iconIndex = -1; // for debug
AddComboBoxItem(name, iconIndex, 0, true);
}
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);
AddComboBoxItem(name, iconIndex, 0, true);
#endif
#endif
return false;
}
@ -596,10 +805,10 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
int index = _headerComboBox.GetCurSel();
if (index >= 0)
{
UString pass = ComboBoxPaths[index];
const UString path = ComboBoxPaths[index];
_headerComboBox.SetCurSel(-1);
// _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
if (BindToPathAndRefresh(pass) == S_OK)
// _headerComboBox.SetText(pass); // it's fix for selecting by mouse.
if (BindToPathAndRefresh(path) == S_OK)
{
PostMsg(kSetFocusToListView);
#ifdef UNDER_CE

View file

@ -583,8 +583,13 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
int cursorIndex = -1;
CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
#if 1 // 0 : for debug local icons loading
if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
_folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
#endif
const bool isFSDrivesFolder = IsFSDrivesFolder();
const bool isArcFolder = IsArcFolder();
if (!IsFSFolder())
{
@ -631,10 +636,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
#else
item.pszText = LPSTR_TEXTCALLBACKW;
#endif
const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
// const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
// g_Ext_to_Icon_Map.GetIconIndex(attrib, itemName);
if (item.iImage < 0)
item.iImage = 0;
item.iImage = 0;
if (_listView.InsertItem(&item) == -1)
return E_FAIL;
listViewItemCount++;
@ -755,11 +761,52 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
}
bool defined = false;
item.iImage = -1;
if (folderGetSystemIconIndex)
{
folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
defined = (item.iImage > 0);
const HRESULT res = folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
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)
@ -769,26 +816,37 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
NCOM::CPropVariant prop;
RINOK(_folder->GetProperty(i, kpidAttrib, &prop))
if (prop.vt == VT_UI4)
{
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))
attrib |= FILE_ATTRIBUTE_DIRECTORY;
if (_currentFolderPrefix.IsEmpty())
{
int iconIndexTemp;
GetRealIconIndex(us2fs((UString)name) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);
item.iImage = iconIndexTemp;
}
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)
item.iImage = 0;
item.iImage = 0; // default image
if (_listView.InsertItem(&item) == -1)
return E_FAIL;
listViewItemCount++;
@ -858,8 +916,8 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
sprintf(s,
// "attribMap = %5d, extMap = %5d, "
"delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d",
// _extToIconMap._attribMap.Size(),
// _extToIconMap._extMap.Size(),
// g_Ext_to_Icon_Map._attribMap.Size(),
// g_Ext_to_Icon_Map._extMap.Size(),
tickCount1 - tickCount0,
tickCount2 - tickCount1,
tickCount3 - tickCount2,

View file

@ -54,9 +54,9 @@ UString RootFolder_GetName_Computer(int &iconIndex);
UString RootFolder_GetName_Computer(int &iconIndex)
{
#ifdef USE_WIN_PATHS
iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
#else
GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY);
#endif
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)
{
iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK);
iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_NETWORK);
return LangString(IDS_NETWORK);
}
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);
}
@ -96,7 +96,7 @@ void CRootFolder::Init()
_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_VOLUMES] = kVolPrefix;
_iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES);
_iconIndices[ROOT_INDEX_VOLUMES] = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
#endif
}

View file

@ -20,16 +20,19 @@
extern bool g_IsNT;
#endif
int GetIconIndexForCSIDL(int csidl)
CExtToIconMap g_Ext_to_Icon_Map;
int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)
{
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, csidl, &pidl);
if (pidl)
{
SHFILEINFO shellInfo;
shellInfo.iIcon = 0;
const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL,
&shellInfo, sizeof(shellInfo),
SHFILEINFO shFileInfo;
shFileInfo.iIcon = -1;
const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl),
FILE_ATTRIBUTE_DIRECTORY,
&shFileInfo, sizeof(shFileInfo),
SHGFI_PIDL | SHGFI_SYSICONINDEX);
/*
IMalloc *pMalloc;
@ -43,9 +46,9 @@ int GetIconIndexForCSIDL(int csidl)
// we use OLE2.dll function here
CoTaskMemFree(pidl);
if (res)
return shellInfo.iIcon;
return shFileInfo.iIcon;
}
return 0;
return -1;
}
#ifndef _UNICODE
@ -60,69 +63,111 @@ static struct C_SHGetFileInfo_Init
f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
"SHGetFileInfoW");
// f_SHGetFileInfoW = NULL; // for debug
}
} g_SHGetFileInfo_Init;
#endif
#ifdef _UNICODE
#define My_SHGetFileInfoW SHGetFileInfoW
#else
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)
return 0;
return g_SHGetFileInfo_Init.f_SHGetFileInfoW
#endif
(pszPath, attrib, psfi, cbFileInfo, uFlags);
return g_SHGetFileInfo_Init.f_SHGetFileInfoW(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
if (!g_IsNT)
#ifndef _UNICODE
if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW)
{
SHFILEINFO shellInfo;
const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
iconIndex = shellInfo.iIcon;
SHFILEINFO shFileInfo;
// ZeroMemory(&shFileInfo, sizeof(shFileInfo));
shFileInfo.iIcon = -1; // optional
const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path),
attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
&shFileInfo, sizeof(shFileInfo),
SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
iconIndex = shFileInfo.iIcon;
return res;
}
else
#endif
#endif
{
SHFILEINFOW shellInfo;
const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
iconIndex = shellInfo.iIcon;
SHFILEINFOW shFileInfo;
// ZeroMemory(&shFileInfo, sizeof(shFileInfo));
shFileInfo.iIcon = -1; // optional
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;
}
}
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
if (!g_IsNT)
{
SHFILEINFO shellInfo;
shellInfo.szTypeName[0] = 0;
DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
SHFILEINFO shFileInfo;
shFileInfo.szTypeName[0] = 0;
DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
if (typeName)
*typeName = GetUnicodeString(shellInfo.szTypeName);
iconIndex = shellInfo.iIcon;
*typeName = GetUnicodeString(shFileInfo.szTypeName);
iconIndex = shFileInfo.iIcon;
return res;
}
else
#endif
{
SHFILEINFOW shellInfo;
shellInfo.szTypeName[0] = 0;
DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
SHFILEINFOW shFileInfo;
shFileInfo.szTypeName[0] = 0;
DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
if (typeName)
*typeName = shellInfo.szTypeName;
iconIndex = shellInfo.iIcon;
*typeName = shFileInfo.szTypeName;
iconIndex = shFileInfo.iIcon;
return res;
}
}
@ -164,6 +209,9 @@ static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar
return -1;
}
// bool DoItemAlwaysStart(const UString &name);
int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
{
int dotPos = -1;
@ -175,6 +223,8 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
break;
if (c == '.')
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;
const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
if (index >= 0)
@ -197,33 +250,43 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
return _attribMap[(unsigned)index].IconIndex;
}
CAttribIconPair pair;
GetRealIconIndex(
pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
#ifdef UNDER_CE
FTEXT("\\")
#endif
FTEXT("__DIR__")
, attrib, pair.IconIndex
, attrib
// , pair.TypeName
);
/*
char s[256];
sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
OutputDebugStringA(s);
*/
pair.Attrib = attrib;
_attribMap.Insert(insertPos, pair);
// if (typeName) *typeName = pair.TypeName;
return pair.IconIndex;
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);
*/
pair.Attrib = attrib;
_attribMap.Insert(insertPos, pair);
// 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;
unsigned insertPos = 0;
const int index = FindInSorted_Ext(_extMap, ext, insertPos);
const int index = FindInSorted_Ext(map, ext, insertPos);
if (index >= 0)
{
const CExtIconPair &pa = _extMap[index];
const CExtIconPair &pa = map[index];
// if (typeName) *typeName = pa.TypeName;
return pa.IconIndex;
}
@ -238,14 +301,14 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
}
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)
{
GetRealIconIndex(
Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
#ifdef UNDER_CE
FTEXT("\\")
#endif
FTEXT("__FILE__.001"), 0, SplitIconIndex);
FTEXT("__FILE__.001"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex);
SplitIconIndex_Defined = true;
}
return SplitIconIndex;
@ -253,27 +316,36 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
CExtIconPair pair;
pair.Ext = ext;
GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);
_extMap.Insert(insertPos, pair);
pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
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;
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;
return (HIMAGELIST)SHGetFileInfo(TEXT(""),
FILE_ATTRIBUTE_NORMAL |
SHFILEINFO shFileInfo;
// shFileInfo.hIcon = NULL; // optional
const DWORD_PTR res = SHGetFileInfo(TEXT(""),
/* FILE_ATTRIBUTE_ARCHIVE | */
FILE_ATTRIBUTE_DIRECTORY,
&shellInfo, sizeof(shellInfo),
&shFileInfo, sizeof(shFileInfo),
SHGFI_USEFILEATTRIBUTES |
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;
}

View file

@ -14,7 +14,6 @@ struct CExtIconPair
UString Ext;
int IconIndex;
// UString TypeName;
// int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
};
@ -23,15 +22,15 @@ struct CAttribIconPair
DWORD Attrib;
int IconIndex;
// UString TypeName;
// int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
};
class CExtToIconMap
struct CExtToIconMap
{
public:
CRecordVector<CAttribIconPair> _attribMap;
CObjectVector<CExtIconPair> _extMap;
CObjectVector<CExtIconPair> _extMap_Normal;
CObjectVector<CExtIconPair> _extMap_Compressed;
int SplitIconIndex;
int SplitIconIndex_Defined;
@ -40,16 +39,27 @@ public:
void Clear()
{
SplitIconIndex_Defined = false;
_extMap.Clear();
_extMap_Normal.Clear();
_extMap_Compressed.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 UString &fileName);
};
DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex);
int GetIconIndexForCSIDL(int csidl);
extern CExtToIconMap g_Ext_to_Icon_Map;
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

View file

@ -387,13 +387,13 @@ void CApp::VerCtrl(unsigned id)
*/
COverwriteDialog dialog;
dialog.OldFileInfo.SetTime(&fdi.Info.ftLastWriteTime);
dialog.OldFileInfo.SetTime(fdi.Info.ftLastWriteTime);
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.Name = fs2us(path2);
dialog.NewFileInfo.Path = fs2us(path2);
dialog.ShowExtraButtons = false;
dialog.DefaultButton_is_NO = true;

View file

@ -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)
{
CProperty &pair = pairs.AddNew();

View file

@ -157,6 +157,31 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
#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

View file

@ -5,6 +5,7 @@
#include "../../C/CpuArch.h"
#include "../Common/IntToString.h"
#include "../Common/StringConvert.h"
#ifdef _WIN32
@ -511,8 +512,6 @@ void GetSysInfo(AString &s1, AString &s2)
}
void GetCpuName(AString &s);
static void AddBracedString(AString &dest, AString &src)
{
if (!src.IsEmpty())
@ -554,9 +553,7 @@ void CCpuName::Fill()
#ifdef MY_CPU_X86_OR_AMD64
{
#if !defined(MY_CPU_AMD64)
if (!z7_x86_cpuid_GetMaxFunc())
s += "x86";
else
if (z7_x86_cpuid_GetMaxFunc())
#endif
{
x86cpuid_to_String(s);
@ -583,43 +580,26 @@ void CCpuName::Fill()
#endif
if (s.IsEmpty())
{
#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
#ifdef _WIN32
{
NRegistry::CKey key;
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];
CByteBuffer bufs[2];
{
@ -627,8 +607,9 @@ void CCpuName::Fill()
{
UInt32 size = 0;
res[i] = key.QueryValue(i == 0 ?
TEXT("Previous Update Revision") :
TEXT("Update Revision"), bufs[i], size);
TEXT("Previous Update Revision") :
TEXT("Update Revision"),
bufs[i], size);
if (res[i] == ERROR_SUCCESS)
if (size != bufs[i].Size())
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
Add_LargePages_String(LargePages);
@ -900,7 +909,7 @@ void GetSystemInfoText(AString &sRes)
}
{
AString s;
GetCpuName(s);
GetCpuName_MultiLine(s);
if (!s.IsEmpty())
{
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)
{

View file

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?define VerMajor = "24" ?>
<?define VerMinor = "07" ?>
<?define VerMinor = "08" ?>
<?define VerBuild = "00" ?>
<?define MmVer = "$(var.VerMajor).$(var.VerMinor)" ?>
<?define MmHex = "$(var.VerMajor)$(var.VerMinor)" ?>

View file

@ -1,6 +1,17 @@
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
-------------------------
- Changes in files: