aboutsummaryrefslogtreecommitdiff
path: root/CPP
diff options
context:
space:
mode:
Diffstat (limited to 'CPP')
-rw-r--r--CPP/7zip/Archive/ElfHandler.cpp30
-rw-r--r--CPP/7zip/Archive/GptHandler.cpp6
-rw-r--r--CPP/7zip/Archive/PeHandler.cpp358
-rw-r--r--CPP/7zip/Archive/QcowHandler.cpp424
-rw-r--r--CPP/7zip/Archive/Rar/Rar5Handler.cpp2
-rw-r--r--CPP/7zip/Archive/Zip/ZipUpdate.cpp17
-rw-r--r--CPP/7zip/UI/Common/Bench.cpp23
-rw-r--r--CPP/7zip/UI/Common/PropIDUtils.cpp13
-rw-r--r--CPP/7zip/UI/Common/Update.cpp18
-rw-r--r--CPP/7zip/UI/Console/ExtractCallbackConsole.cpp6
-rw-r--r--CPP/7zip/UI/Explorer/ContextMenu.cpp3
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.cpp18
-rw-r--r--CPP/7zip/UI/FileManager/App.cpp1
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp14
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog2.cpp13
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp16
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.h4
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.cpp56
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.cpp31
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.h35
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp16
-rw-r--r--CPP/7zip/UI/FileManager/NetFolder.cpp25
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.cpp238
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.h52
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.rc4
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialogRes.h8
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp19
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h14
-rw-r--r--CPP/7zip/UI/FileManager/PanelCopy.cpp4
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp355
-rw-r--r--CPP/7zip/UI/FileManager/PanelItems.cpp92
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp10
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.cpp214
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.h30
-rw-r--r--CPP/7zip/UI/FileManager/VerCtrl.cpp8
-rw-r--r--CPP/7zip/UI/GUI/HashGUI.cpp22
-rw-r--r--CPP/Windows/FileSystem.cpp25
-rw-r--r--CPP/Windows/SystemInfo.cpp105
38 files changed, 1541 insertions, 788 deletions
diff --git a/CPP/7zip/Archive/ElfHandler.cpp b/CPP/7zip/Archive/ElfHandler.cpp
index 305173b..df22995 100644
--- a/CPP/7zip/Archive/ElfHandler.cpp
+++ b/CPP/7zip/Archive/ElfHandler.cpp
@@ -628,6 +628,7 @@ static const char * const g_Machines[] =
628static const CUInt32PCharPair g_MachinePairs[] = 628static const CUInt32PCharPair g_MachinePairs[] =
629{ 629{
630 { 243, "RISC-V" }, 630 { 243, "RISC-V" },
631 { 258, "LoongArch" },
631 { 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI) 632 { 0x9026, "Alpha" }, // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)
632 { 0xbaab, "Xilinx MicroBlaze" } 633 { 0xbaab, "Xilinx MicroBlaze" }
633}; 634};
@@ -853,10 +854,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
853 else if (_header.Machine == k_Machine_MIPS) 854 else if (_header.Machine == k_Machine_MIPS)
854 { 855 {
855 const UInt32 ver = flags >> 28; 856 const UInt32 ver = flags >> 28;
856 s += "v"; 857 s.Add_Char('v');
857 s.Add_UInt32(ver); 858 s.Add_UInt32(ver);
858 flags &= ((UInt32)1 << 28) - 1; 859 flags &= ((UInt32)1 << 28) - 1;
859
860 const UInt32 abi = (flags >> 12) & 7; 860 const UInt32 abi = (flags >> 12) & 7;
861 if (abi) 861 if (abi)
862 { 862 {
@@ -864,7 +864,6 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
864 s.Add_UInt32(abi); 864 s.Add_UInt32(abi);
865 } 865 }
866 flags &= ~((UInt32)7 << 12); 866 flags &= ~((UInt32)7 << 12);
867
868 s.Add_Space(); 867 s.Add_Space();
869 s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags); 868 s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);
870 } 869 }
@@ -885,6 +884,31 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
885 flags &= ~(UInt32)6; 884 flags &= ~(UInt32)6;
886 s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags); 885 s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);
887 } 886 }
887#if 0
888#define k_Machine_LOONGARCH 258
889 else if (_header.Machine == k_Machine_LOONGARCH)
890 {
891 s += "ABI:";
892 s.Add_UInt32((flags >> 6) & 3);
893 s.Add_Dot();
894 s.Add_UInt32((flags >> 3) & 7);
895 s.Add_Dot();
896#if 1
897 s.Add_UInt32(flags & 7);
898#else
899 static const char k_LoongArch_Float_Type[8] = { '0', 's', 'f', 'd', '4' ,'5', '6', '7' };
900 s.Add_Char(k_LoongArch_Float_Type[flags & 7]);
901#endif
902 flags &= ~(UInt32)0xff;
903 if (flags)
904 {
905 s.Add_Colon();
906 char sz[16];
907 ConvertUInt32ToHex(flags, sz);
908 s += sz;
909 }
910 }
911#endif
888 else 912 else
889 { 913 {
890 char sz[16]; 914 char sz[16];
diff --git a/CPP/7zip/Archive/GptHandler.cpp b/CPP/7zip/Archive/GptHandler.cpp
index 23a1db6..4c291c4 100644
--- a/CPP/7zip/Archive/GptHandler.cpp
+++ b/CPP/7zip/Archive/GptHandler.cpp
@@ -111,6 +111,12 @@ static const CPartType kPartTypes[] =
111 111
112 { 0x0FC63DAF, NULL, "Linux Data" }, 112 { 0x0FC63DAF, NULL, "Linux Data" },
113 { 0x0657FD6D, NULL, "Linux Swap" }, 113 { 0x0657FD6D, NULL, "Linux Swap" },
114 { 0x44479540, NULL, "Linux root (x86)" },
115 { 0x4F68BCE3, NULL, "Linux root (x86-64)" },
116 { 0x69DAD710, NULL, "Linux root (ARM)" },
117 { 0xB921B045, NULL, "Linux root (ARM64)" },
118 { 0x993D8D3D, NULL, "Linux root (IA-64)" },
119
114 120
115 { 0x83BD6B9D, NULL, "FreeBSD Boot" }, 121 { 0x83BD6B9D, NULL, "FreeBSD Boot" },
116 { 0x516E7CB4, NULL, "FreeBSD Data" }, 122 { 0x516E7CB4, NULL, "FreeBSD Data" },
diff --git a/CPP/7zip/Archive/PeHandler.cpp b/CPP/7zip/Archive/PeHandler.cpp
index 0cab820..8a0ff05 100644
--- a/CPP/7zip/Archive/PeHandler.cpp
+++ b/CPP/7zip/Archive/PeHandler.cpp
@@ -180,9 +180,32 @@ struct CDirLink
180 } 180 }
181}; 181};
182 182
183
184// IMAGE_DIRECTORY_ENTRY_*
185static const char * const g_Dir_Names[] =
186{
187 "EXPORT"
188 , "IMPORT"
189 , "RESOURCE"
190 , "EXCEPTION"
191 , "SECURITY"
192 , "BASERELOC"
193 , "DEBUG"
194 , "ARCHITECTURE" // "COPYRIGHT"
195 , "GLOBALPTR"
196 , "TLS"
197 , "LOAD_CONFIG"
198 , "BOUND_IMPORT"
199 , "IAT"
200 , "DELAY_IMPORT"
201 , "COM_DESCRIPTOR"
202};
203
183enum 204enum
184{ 205{
206 kDirLink_EXCEPTION = 3,
185 kDirLink_Certificate = 4, 207 kDirLink_Certificate = 4,
208 kDirLink_BASERELOC = 5,
186 kDirLink_Debug = 6 209 kDirLink_Debug = 6
187}; 210};
188 211
@@ -229,7 +252,7 @@ struct COptHeader
229 UInt32 UninitDataSize; 252 UInt32 UninitDataSize;
230 253
231 // UInt32 AddressOfEntryPoint; 254 // UInt32 AddressOfEntryPoint;
232 // UInt32 BaseOfCode; 255 // UInt32 BaseOfCode; // VA(.text) == 0x1000 in most cases
233 // UInt32 BaseOfData32; 256 // UInt32 BaseOfData32;
234 UInt64 ImageBase; 257 UInt64 ImageBase;
235 258
@@ -273,6 +296,7 @@ struct COptHeader
273 } 296 }
274}; 297};
275 298
299// size is 16-bit
276bool COptHeader::Parse(const Byte *p, UInt32 size) 300bool COptHeader::Parse(const Byte *p, UInt32 size)
277{ 301{
278 if (size < k_OptHeader32_Size_MIN) 302 if (size < k_OptHeader32_Size_MIN)
@@ -334,14 +358,18 @@ bool COptHeader::Parse(const Byte *p, UInt32 size)
334 pos = 92; 358 pos = 92;
335 } 359 }
336 360
337 G32(pos, NumDirItems); 361 UInt32 numDirItems;
338 if (NumDirItems > (1 << 16)) 362 G32(pos, numDirItems);
363 NumDirItems = numDirItems;
364 if (numDirItems > (1 << 13))
339 return false; 365 return false;
340 pos += 4; 366 pos += 4;
341 if (pos + 8 * NumDirItems > size) 367 if (pos + 8 * numDirItems > size)
342 return false; 368 return false;
343 memset((void *)DirItems, 0, sizeof(DirItems)); 369 memset((void *)DirItems, 0, sizeof(DirItems));
344 for (UInt32 i = 0; i < NumDirItems && i < kNumDirItemsMax; i++) 370 if (numDirItems > kNumDirItemsMax)
371 numDirItems = kNumDirItemsMax;
372 for (UInt32 i = 0; i < numDirItems; i++)
345 DirItems[i].Parse(p + pos + i * 8); 373 DirItems[i].Parse(p + pos + i * 8);
346 return true; 374 return true;
347} 375}
@@ -352,27 +380,41 @@ struct CSection
352{ 380{
353 AString Name; 381 AString Name;
354 382
383 UInt32 ExtractSize;
355 UInt32 VSize; 384 UInt32 VSize;
356 UInt32 Va; 385 UInt32 Va;
357 UInt32 PSize; 386 UInt32 PSize;
358 UInt32 Pa; 387 UInt32 Pa;
359 UInt32 Flags; 388 UInt32 Flags;
360 UInt32 Time; 389 UInt32 Time;
361 // UInt16 NumRelocs; 390 // UInt16 NumRelocs; // is set to zero for executable images
362 bool IsRealSect; 391 bool IsRealSect;
363 bool IsDebug; 392 bool IsDebug;
364 bool IsAdditionalSection; 393 bool IsAdditionalSection;
365 394
366 CSection(): IsRealSect(false), IsDebug(false), IsAdditionalSection(false) {} 395 CSection():
396 ExtractSize(0),
397 IsRealSect(false),
398 IsDebug(false),
399 IsAdditionalSection(false)
400 // , NumRelocs(0)
401 {}
367 402
368 UInt32 GetSizeExtract() const { return PSize; } 403 void Set_Size_for_all(UInt32 size)
369 UInt32 GetSizeMin() const { return MyMin(PSize, VSize); } 404 {
405 PSize = VSize = ExtractSize = size;
406 }
407
408 UInt32 GetSize_Extract() const
409 {
410 return ExtractSize;
411 }
370 412
371 void UpdateTotalSize(UInt32 &totalSize) const 413 void UpdateTotalSize(UInt32 &totalSize) const
372 { 414 {
373 UInt32 t = Pa + PSize; 415 const UInt32 t = Pa + PSize;
374 if (totalSize < t) 416 if (totalSize < t)
375 totalSize = t; 417 totalSize = t;
376 } 418 }
377 419
378 void Parse(const Byte *p); 420 void Parse(const Byte *p);
@@ -380,8 +422,8 @@ struct CSection
380 int Compare(const CSection &s) const 422 int Compare(const CSection &s) const
381 { 423 {
382 RINOZ(MyCompare(Pa, s.Pa)) 424 RINOZ(MyCompare(Pa, s.Pa))
383 UInt32 size1 = GetSizeExtract(); 425 const UInt32 size1 = GetSize_Extract();
384 UInt32 size2 = s.GetSizeExtract(); 426 const UInt32 size2 = s.GetSize_Extract();
385 return MyCompare(size1, size2); 427 return MyCompare(size1, size2);
386 } 428 }
387}; 429};
@@ -402,6 +444,10 @@ void CSection::Parse(const Byte *p)
402 G32(20, Pa); 444 G32(20, Pa);
403 // G16(32, NumRelocs); 445 // G16(32, NumRelocs);
404 G32(36, Flags); 446 G32(36, Flags);
447 // v24.08: we extract only useful data (without extra padding bytes).
448 // VSize == 0 is not expected, but we support that case too.
449 // return (VSize && VSize < PSize) ? VSize : PSize;
450 ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
405} 451}
406 452
407 453
@@ -508,6 +554,7 @@ static const CUInt32PCharPair g_MachinePairs[] =
508 { 0x01D3, "AM33" }, 554 { 0x01D3, "AM33" },
509 { 0x01F0, "PPC" }, 555 { 0x01F0, "PPC" },
510 { 0x01F1, "PPC-FP" }, 556 { 0x01F1, "PPC-FP" },
557 { 0x01F2, "PPC-BE" },
511 { 0x0200, "IA-64" }, 558 { 0x0200, "IA-64" },
512 { 0x0266, "MIPS-16" }, 559 { 0x0266, "MIPS-16" },
513 { 0x0284, "Alpha-64" }, 560 { 0x0284, "Alpha-64" },
@@ -830,11 +877,11 @@ enum
830 kpidStackReserve, 877 kpidStackReserve,
831 kpidStackCommit, 878 kpidStackCommit,
832 kpidHeapReserve, 879 kpidHeapReserve,
833 kpidHeapCommit, 880 kpidHeapCommit
834 kpidImageBase 881 // , kpidImageBase
835 // kpidAddressOfEntryPoint, 882 // , kpidAddressOfEntryPoint
836 // kpidBaseOfCode, 883 // , kpidBaseOfCode
837 // kpidBaseOfData32, 884 // , kpidBaseOfData32
838}; 885};
839 886
840static const CStatProp kArcProps[] = 887static const CStatProp kArcProps[] =
@@ -864,14 +911,16 @@ static const CStatProp kArcProps[] =
864 { "Stack Commit", kpidStackCommit, VT_UI8}, 911 { "Stack Commit", kpidStackCommit, VT_UI8},
865 { "Heap Reserve", kpidHeapReserve, VT_UI8}, 912 { "Heap Reserve", kpidHeapReserve, VT_UI8},
866 { "Heap Commit", kpidHeapCommit, VT_UI8}, 913 { "Heap Commit", kpidHeapCommit, VT_UI8},
867 { "Image Base", kpidImageBase, VT_UI8}, 914 { NULL, kpidVa, VT_UI8 }, // "Image Base", kpidImageBase, VT_UI8
868 { NULL, kpidComment, VT_BSTR}, 915 { NULL, kpidComment, VT_BSTR}
869 916
870 // { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}, 917 // , { "Address Of Entry Point", kpidAddressOfEntryPoint, VT_UI8}
871 // { "Base Of Code", kpidBaseOfCode, VT_UI8}, 918 // , { "Base Of Code", kpidBaseOfCode, VT_UI8}
872 // { "Base Of Data", kpidBaseOfData32, VT_UI8}, 919 // , { "Base Of Data", kpidBaseOfData32, VT_UI8}
873}; 920};
874 921
922// #define kpid_NumRelocs 250
923
875static const Byte kProps[] = 924static const Byte kProps[] =
876{ 925{
877 kpidPath, 926 kpidPath,
@@ -880,7 +929,8 @@ static const Byte kProps[] =
880 kpidVirtualSize, 929 kpidVirtualSize,
881 kpidCharacts, 930 kpidCharacts,
882 kpidOffset, 931 kpidOffset,
883 kpidVa, 932 kpidVa
933 // , kpid_NumRelocs
884}; 934};
885 935
886IMP_IInArchive_Props 936IMP_IInArchive_Props
@@ -899,7 +949,42 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
899 switch (propID) 949 switch (propID)
900 { 950 {
901 case kpidPhySize: prop = _totalSize; break; 951 case kpidPhySize: prop = _totalSize; break;
902 case kpidComment: if (!_versionFullString.IsEmpty()) prop = _versionFullString; break; 952 case kpidComment:
953 {
954 UString s (_versionFullString);
955 s.Add_LF();
956 s += "Data Directories: ";
957 s.Add_UInt32(_optHeader.NumDirItems);
958 s.Add_LF();
959 s.Add_Char('{');
960 s.Add_LF();
961 for (unsigned i = 0; i < _optHeader.NumDirItems
962 && i < Z7_ARRAY_SIZE(_optHeader.DirItems); i++)
963 {
964 const CDirLink &di = _optHeader.DirItems[i];
965 if (di.Va == 0 && di.Size == 0)
966 continue;
967 s += "index=";
968 s.Add_UInt32(i);
969
970 if (i < Z7_ARRAY_SIZE(g_Dir_Names))
971 {
972 s += " name=";
973 s += g_Dir_Names[i];
974 }
975 s += " VA=0x";
976 char temp[16];
977 ConvertUInt32ToHex(di.Va, temp);
978 s += temp;
979 s += " Size=";
980 s.Add_UInt32(di.Size);
981 s.Add_LF();
982 }
983 s.Add_Char('}');
984 s.Add_LF();
985 prop = s;
986 break;
987 }
903 case kpidShortComment: 988 case kpidShortComment:
904 if (!_versionShortString.IsEmpty()) 989 if (!_versionShortString.IsEmpty())
905 prop = _versionShortString; 990 prop = _versionShortString;
@@ -969,8 +1054,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
969 case kpidStackCommit: prop = _optHeader.StackCommit; break; 1054 case kpidStackCommit: prop = _optHeader.StackCommit; break;
970 case kpidHeapReserve: prop = _optHeader.HeapReserve; break; 1055 case kpidHeapReserve: prop = _optHeader.HeapReserve; break;
971 case kpidHeapCommit: prop = _optHeader.HeapCommit; break; 1056 case kpidHeapCommit: prop = _optHeader.HeapCommit; break;
972 1057 case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:
973 case kpidImageBase: prop = _optHeader.ImageBase; break;
974 // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break; 1058 // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;
975 // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break; 1059 // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;
976 // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break; 1060 // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;
@@ -1130,7 +1214,8 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
1130 prop = MultiByteToUnicodeString(s); 1214 prop = MultiByteToUnicodeString(s);
1131 break; 1215 break;
1132 } 1216 }
1133 case kpidSize: prop = (UInt64)item.PSize; break; 1217 case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
1218 // case kpid_NumRelocs: prop = (UInt32)item.NumRelocs; break;
1134 case kpidPackSize: prop = (UInt64)item.PSize; break; 1219 case kpidPackSize: prop = (UInt64)item.PSize; break;
1135 case kpidVirtualSize: prop = (UInt64)item.VSize; break; 1220 case kpidVirtualSize: prop = (UInt64)item.VSize; break;
1136 case kpidOffset: prop = item.Pa; break; 1221 case kpidOffset: prop = item.Pa; break;
@@ -1229,7 +1314,7 @@ HRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)
1229 sect.Time = de.Time; 1314 sect.Time = de.Time;
1230 sect.Va = de.Va; 1315 sect.Va = de.Va;
1231 sect.Pa = de.Pa; 1316 sect.Pa = de.Pa;
1232 sect.PSize = sect.VSize = de.Size; 1317 sect.Set_Size_for_all(de.Size);
1233 } 1318 }
1234 buf += kEntrySize; 1319 buf += kEntrySize;
1235 } 1320 }
@@ -1757,7 +1842,7 @@ static void CopyToUString(const Byte *p, UString &s)
1757{ 1842{
1758 for (;;) 1843 for (;;)
1759 { 1844 {
1760 wchar_t c = (wchar_t)Get16(p); 1845 const wchar_t c = (wchar_t)Get16(p);
1761 p += 2; 1846 p += 2;
1762 if (c == 0) 1847 if (c == 0)
1763 return; 1848 return;
@@ -1765,6 +1850,16 @@ static void CopyToUString(const Byte *p, UString &s)
1765 } 1850 }
1766} 1851}
1767 1852
1853static void CopyToUString_ByLen16(const Byte *p, unsigned numChars16, UString &s)
1854{
1855 for (; numChars16; numChars16--)
1856 {
1857 const wchar_t c = (wchar_t)Get16(p);
1858 p += 2;
1859 s += c;
1860 }
1861}
1862
1768static bool CompareWStrStrings(const Byte *p, const char *s) 1863static bool CompareWStrStrings(const Byte *p, const char *s)
1769{ 1864{
1770 unsigned pos = 0; 1865 unsigned pos = 0;
@@ -1783,7 +1878,7 @@ struct CVersionBlock
1783{ 1878{
1784 UInt32 TotalLen; 1879 UInt32 TotalLen;
1785 UInt32 ValueLen; 1880 UInt32 ValueLen;
1786 bool IsTextValue; 1881 unsigned IsTextValue;
1787 unsigned StrSize; 1882 unsigned StrSize;
1788 1883
1789 bool Parse(const Byte *p, UInt32 size); 1884 bool Parse(const Byte *p, UInt32 size);
@@ -1802,6 +1897,23 @@ static int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size)
1802 } 1897 }
1803} 1898}
1804 1899
1900static int Get_Utf16Str_Len_InBytes_AllowNonZeroTail(const Byte *p, size_t size)
1901{
1902 unsigned pos = 0;
1903 for (;;)
1904 {
1905 if (pos + 1 >= size)
1906 {
1907 if (pos == size)
1908 return (int)pos;
1909 return -1;
1910 }
1911 if (Get16(p + pos) == 0)
1912 return (int)pos;
1913 pos += 2;
1914 }
1915}
1916
1805static const unsigned k_ResoureBlockHeader_Size = 6; 1917static const unsigned k_ResoureBlockHeader_Size = 6;
1806 1918
1807bool CVersionBlock::Parse(const Byte *p, UInt32 size) 1919bool CVersionBlock::Parse(const Byte *p, UInt32 size)
@@ -1812,14 +1924,12 @@ bool CVersionBlock::Parse(const Byte *p, UInt32 size)
1812 ValueLen = Get16(p + 2); 1924 ValueLen = Get16(p + 2);
1813 if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size) 1925 if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)
1814 return false; 1926 return false;
1815 switch (Get16(p + 4)) 1927 IsTextValue = Get16(p + 4);
1816 { 1928 if (IsTextValue > 1)
1817 case 0: IsTextValue = false; break; 1929 return false;
1818 case 1: IsTextValue = true; break;
1819 default: return false;
1820 }
1821 StrSize = 0; 1930 StrSize = 0;
1822 const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size, TotalLen - k_ResoureBlockHeader_Size); 1931 const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size,
1932 TotalLen - k_ResoureBlockHeader_Size);
1823 if (t < 0) 1933 if (t < 0)
1824 return false; 1934 return false;
1825 StrSize = (unsigned)t; 1935 StrSize = (unsigned)t;
@@ -1859,7 +1969,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1859 // if (size != vb.TotalLen) return false; 1969 // if (size != vb.TotalLen) return false;
1860 */ 1970 */
1861 if (size > vb.TotalLen) 1971 if (size > vb.TotalLen)
1862 size = vb.TotalLen; 1972 size = vb.TotalLen;
1863 CMy_VS_FIXEDFILEINFO FixedFileInfo; 1973 CMy_VS_FIXEDFILEINFO FixedFileInfo;
1864 if (!FixedFileInfo.Parse(p + pos)) 1974 if (!FixedFileInfo.Parse(p + pos))
1865 return false; 1975 return false;
@@ -1880,7 +1990,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1880 return false; 1990 return false;
1881 if (vb.ValueLen != 0) 1991 if (vb.ValueLen != 0)
1882 return false; 1992 return false;
1883 UInt32 endPos = pos + vb.TotalLen; 1993 const UInt32 endPos = pos + vb.TotalLen;
1884 pos += k_ResoureBlockHeader_Size; 1994 pos += k_ResoureBlockHeader_Size;
1885 1995
1886 f.AddSpaces(2); 1996 f.AddSpaces(2);
@@ -1901,7 +2011,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1901 CVersionBlock vb2; 2011 CVersionBlock vb2;
1902 if (!vb2.Parse(p + pos, endPos - pos)) 2012 if (!vb2.Parse(p + pos, endPos - pos))
1903 return false; 2013 return false;
1904 UInt32 endPos2 = pos + vb2.TotalLen; 2014 const UInt32 endPos2 = pos + vb2.TotalLen;
1905 if (vb2.IsTextValue) 2015 if (vb2.IsTextValue)
1906 return false; 2016 return false;
1907 pos += k_ResoureBlockHeader_Size; 2017 pos += k_ResoureBlockHeader_Size;
@@ -1919,9 +2029,9 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1919 UInt32 num = (vb2.ValueLen >> 2); 2029 UInt32 num = (vb2.ValueLen >> 2);
1920 for (; num != 0; num--, pos += 4) 2030 for (; num != 0; num--, pos += 4)
1921 { 2031 {
1922 UInt32 dw = Get32(p + pos); 2032 const UInt32 dw = Get32(p + pos);
1923 UInt32 lang = LOWORD(dw); 2033 const UInt32 lang = LOWORD(dw);
1924 UInt32 codePage = HIWORD(dw); 2034 const UInt32 codePage = HIWORD(dw);
1925 2035
1926 f.AddString(", "); 2036 f.AddString(", ");
1927 PrintHex(f, lang); 2037 PrintHex(f, lang);
@@ -1936,7 +2046,6 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1936 if (!CompareWStrStrings(p + pos, "StringFileInfo")) 2046 if (!CompareWStrStrings(p + pos, "StringFileInfo"))
1937 return false; 2047 return false;
1938 pos += vb.StrSize + 2; 2048 pos += vb.StrSize + 2;
1939
1940 for (;;) 2049 for (;;)
1941 { 2050 {
1942 pos += (4 - pos) & 3; 2051 pos += (4 - pos) & 3;
@@ -1945,7 +2054,7 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1945 CVersionBlock vb2; 2054 CVersionBlock vb2;
1946 if (!vb2.Parse(p + pos, endPos - pos)) 2055 if (!vb2.Parse(p + pos, endPos - pos))
1947 return false; 2056 return false;
1948 UInt32 endPos2 = pos + vb2.TotalLen; 2057 const UInt32 endPos2 = pos + vb2.TotalLen;
1949 if (vb2.ValueLen != 0) 2058 if (vb2.ValueLen != 0)
1950 return false; 2059 return false;
1951 pos += k_ResoureBlockHeader_Size; 2060 pos += k_ResoureBlockHeader_Size;
@@ -1967,9 +2076,8 @@ static bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector
1967 CVersionBlock vb3; 2076 CVersionBlock vb3;
1968 if (!vb3.Parse(p + pos, endPos2 - pos)) 2077 if (!vb3.Parse(p + pos, endPos2 - pos))
1969 return false; 2078 return false;
1970 // ValueLen sometimes is a number of characters (not bytes)? 2079 // ValueLen is a number of 16-bit characters (usually it includes zero tail character).
1971 // So we don't use it. 2080 const UInt32 endPos3 = pos + vb3.TotalLen;
1972 UInt32 endPos3 = pos + vb3.TotalLen;
1973 pos += k_ResoureBlockHeader_Size; 2081 pos += k_ResoureBlockHeader_Size;
1974 2082
1975 // we don't write string if it's not text 2083 // 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
1984 pos += vb3.StrSize + 2; 2092 pos += vb3.StrSize + 2;
1985 2093
1986 pos += (4 - pos) & 3; 2094 pos += (4 - pos) & 3;
1987 if (vb3.ValueLen > 0 && pos + 2 <= endPos3) 2095 if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)
1988 { 2096 {
1989 f.AddChar(','); 2097 f.AddChar(',');
1990 f.AddSpaces((34 - (int)vb3.StrSize) / 2); 2098 f.AddSpaces((34 - (int)vb3.StrSize) / 2);
1991 const int sLen = Get_Utf16Str_Len_InBytes(p + pos, endPos3 - pos); 2099 // vb3.TotalLen for some PE files (not from msvc) doesn't include tail zero at the end of Value string.
2100 // we allow that minor error.
2101 const int sLen = Get_Utf16Str_Len_InBytes_AllowNonZeroTail(p + pos, endPos3 - pos);
1992 if (sLen < 0) 2102 if (sLen < 0)
1993 return false; 2103 return false;
2104 /*
2105 if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&
2106 vb3.ValueLen != (unsigned)sLen / 2)
2107 return false;
2108 */
1994 AddParamString(f, p + pos, (unsigned)sLen); 2109 AddParamString(f, p + pos, (unsigned)sLen);
1995 CopyToUString(p + pos, value); 2110 CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);
1996 pos += (unsigned)sLen + 2; 2111 // pos += (unsigned)sLen + 2;
1997 } 2112 }
1998 AddToUniqueUStringVector(keys, key, value); 2113 AddToUniqueUStringVector(keys, key, value);
1999 } 2114 }
2000 pos = endPos3; 2115 pos = endPos3;
2001 f.NewLine(); 2116 f.NewLine();
2002 } 2117 }
2118 pos = endPos2;
2003 f.CloseBlock(4); 2119 f.CloseBlock(4);
2004 } 2120 }
2005 } 2121 }
2006 f.CloseBlock(2); 2122 f.CloseBlock(2);
2123 pos = endPos;
2007 } 2124 }
2008 2125
2009 f.CloseBlock(0); 2126 f.CloseBlock(0);
@@ -2218,7 +2335,7 @@ HRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchi
2218 2335
2219 if (sect2.PSize != 0) 2336 if (sect2.PSize != 0)
2220 { 2337 {
2221 sect2.VSize = sect2.PSize; 2338 sect2.ExtractSize = sect2.VSize = sect2.PSize;
2222 sect2.Name = ".rsrc_1"; 2339 sect2.Name = ".rsrc_1";
2223 sect2.Time = 0; 2340 sect2.Time = 0;
2224 sect2.IsAdditionalSection = true; 2341 sect2.IsAdditionalSection = true;
@@ -2337,6 +2454,20 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
2337 CSection &sect = _sections.AddNew(); 2454 CSection &sect = _sections.AddNew();
2338 sect.Parse(buffer + pos); 2455 sect.Parse(buffer + pos);
2339 sect.IsRealSect = true; 2456 sect.IsRealSect = true;
2457 if (sect.Name.IsEqualTo(".reloc"))
2458 {
2459 const CDirLink &dl = _optHeader.DirItems[kDirLink_BASERELOC];
2460 if (dl.Va == sect.Va &&
2461 dl.Size <= sect.PSize)
2462 sect.ExtractSize = dl.Size;
2463 }
2464 else if (sect.Name.IsEqualTo(".pdata"))
2465 {
2466 const CDirLink &dl = _optHeader.DirItems[kDirLink_EXCEPTION];
2467 if (dl.Va == sect.Va &&
2468 dl.Size <= sect.PSize)
2469 sect.ExtractSize = dl.Size;
2470 }
2340 2471
2341 /* PE pre-file in .hxs file has errors: 2472 /* PE pre-file in .hxs file has errors:
2342 PSize of resource is larger than real size. 2473 PSize of resource is larger than real size.
@@ -2390,7 +2521,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
2390 sect.Name = "CERTIFICATE"; 2521 sect.Name = "CERTIFICATE";
2391 sect.Va = 0; 2522 sect.Va = 0;
2392 sect.Pa = certLink.Va; 2523 sect.Pa = certLink.Va;
2393 sect.PSize = sect.VSize = certLink.Size; 2524 sect.Set_Size_for_all(certLink.Size);
2394 sect.UpdateTotalSize(_totalSize); 2525 sect.UpdateTotalSize(_totalSize);
2395 } 2526 }
2396 2527
@@ -2448,7 +2579,7 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
2448 sect.Name = "COFF_SYMBOLS"; 2579 sect.Name = "COFF_SYMBOLS";
2449 sect.Va = 0; 2580 sect.Va = 0;
2450 sect.Pa = _header.PointerToSymbolTable; 2581 sect.Pa = _header.PointerToSymbolTable;
2451 sect.PSize = sect.VSize = size; 2582 sect.Set_Size_for_all(size);
2452 sect.UpdateTotalSize(_totalSize); 2583 sect.UpdateTotalSize(_totalSize);
2453 } 2584 }
2454 2585
@@ -2464,11 +2595,11 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)
2464 { 2595 {
2465 CSection &s2 = _sections.AddNew(); 2596 CSection &s2 = _sections.AddNew();
2466 s2.Pa = s2.Va = limit; 2597 s2.Pa = s2.Va = limit;
2467 s2.PSize = s2.VSize = s.Pa - limit; 2598 s2.Set_Size_for_all(s.Pa - limit);
2468 s2.IsAdditionalSection = true; 2599 s2.IsAdditionalSection = true;
2469 s2.Name = '['; 2600 s2.Name.Add_Char('[');
2470 s2.Name.Add_UInt32(num++); 2601 s2.Name.Add_UInt32(num++);
2471 s2.Name += ']'; 2602 s2.Name.Add_Char(']');
2472 limit = s.Pa; 2603 limit = s.Pa;
2473 } 2604 }
2474 UInt32 next = s.Pa + s.PSize; 2605 UInt32 next = s.Pa + s.PSize;
@@ -2700,29 +2831,26 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2700 else if (mixItem.ResourceIndex >= 0) 2831 else if (mixItem.ResourceIndex >= 0)
2701 size = _items[mixItem.ResourceIndex].GetSize(); 2832 size = _items[mixItem.ResourceIndex].GetSize();
2702 else 2833 else
2703 size = _sections[mixItem.SectionIndex].GetSizeExtract(); 2834 size = _sections[mixItem.SectionIndex].GetSize_Extract();
2704 totalSize += size; 2835 totalSize += size;
2705 } 2836 }
2706 extractCallback->SetTotal(totalSize); 2837 RINOK(extractCallback->SetTotal(totalSize))
2707
2708 UInt64 currentTotalSize = 0;
2709 UInt64 currentItemSize;
2710
2711 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
2712 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
2713 2838
2714 CLocalProgress *lps = new CLocalProgress; 2839 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
2715 CMyComPtr<ICompressProgressInfo> progress = lps; 2840 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
2716 lps->Init(extractCallback, false); 2841 lps->Init(extractCallback, false);
2842 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
2843 inStream->SetStream(_stream);
2717 2844
2718 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 2845 totalSize = 0;
2719 CMyComPtr<ISequentialInStream> inStream(streamSpec); 2846 UInt64 currentItemSize;
2720 streamSpec->SetStream(_stream); 2847
2721 2848 for (i = 0;; i++, totalSize += currentItemSize)
2722 for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
2723 { 2849 {
2724 lps->InSize = lps->OutSize = currentTotalSize; 2850 lps->InSize = lps->OutSize = totalSize;
2725 RINOK(lps->SetCur()) 2851 RINOK(lps->SetCur())
2852 if (i >= numItems)
2853 break;
2726 const Int32 askMode = testMode ? 2854 const Int32 askMode = testMode ?
2727 NExtract::NAskMode::kTest : 2855 NExtract::NAskMode::kTest :
2728 NExtract::NAskMode::kExtract; 2856 NExtract::NAskMode::kExtract;
@@ -2776,15 +2904,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
2776 } 2904 }
2777 else 2905 else
2778 { 2906 {
2779 currentItemSize = sect.GetSizeExtract(); 2907 currentItemSize = sect.GetSize_Extract();
2780 if (!testMode && !outStream) 2908 if (!testMode && !outStream)
2781 continue; 2909 continue;
2782 2910
2783 RINOK(extractCallback->PrepareOperation(askMode)) 2911 RINOK(extractCallback->PrepareOperation(askMode))
2784 RINOK(InStream_SeekSet(_stream, sect.Pa)) 2912 RINOK(InStream_SeekSet(_stream, sect.Pa))
2785 streamSpec->Init(currentItemSize); 2913 inStream->Init(currentItemSize);
2786 RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress)) 2914 RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))
2787 isOk = (copyCoderSpec->TotalSize == currentItemSize); 2915 isOk = (copyCoder->TotalSize == currentItemSize);
2788 } 2916 }
2789 2917
2790 outStream.Release(); 2918 outStream.Release();
@@ -2804,7 +2932,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
2804 const CMixItem &mixItem = _mixItems[index]; 2932 const CMixItem &mixItem = _mixItems[index];
2805 const CSection &sect = _sections[mixItem.SectionIndex]; 2933 const CSection &sect = _sections[mixItem.SectionIndex];
2806 if (mixItem.IsSectionItem()) 2934 if (mixItem.IsSectionItem())
2807 return CreateLimitedInStream(_stream, sect.Pa, sect.PSize, stream); 2935 return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);
2808 2936
2809 CBufInStream *inStreamSpec = new CBufInStream; 2937 CBufInStream *inStreamSpec = new CBufInStream;
2810 CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec; 2938 CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;
@@ -2964,7 +3092,7 @@ bool CHeader::Parse(const Byte *p)
2964 G32(12, BaseOfCode); 3092 G32(12, BaseOfCode);
2965 G64(16, ImageBase); 3093 G64(16, ImageBase);
2966 */ 3094 */
2967 for (int i = 0; i < 2; i++) 3095 for (unsigned i = 0; i < 2; i++)
2968 { 3096 {
2969 CDataDir &dd = DataDir[i]; 3097 CDataDir &dd = DataDir[i];
2970 dd.Parse(p + 24 + i * 8); 3098 dd.Parse(p + 24 + i * 8);
@@ -2997,6 +3125,7 @@ struct CSection
2997{ 3125{
2998 Byte Name[NPe::kNameSize]; 3126 Byte Name[NPe::kNameSize];
2999 3127
3128 UInt32 ExtractSize;
3000 UInt32 VSize; 3129 UInt32 VSize;
3001 UInt32 Va; 3130 UInt32 Va;
3002 UInt32 PSize; 3131 UInt32 PSize;
@@ -3013,6 +3142,7 @@ struct CSection
3013 G32(20, Pa); 3142 G32(20, Pa);
3014 // G32(p + 32, NumRelocs); 3143 // G32(p + 32, NumRelocs);
3015 G32(36, Flags); 3144 G32(36, Flags);
3145 ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;
3016 } 3146 }
3017 3147
3018 bool Check() const 3148 bool Check() const
@@ -3022,11 +3152,16 @@ struct CSection
3022 PSize <= ((UInt32)1 << 30); 3152 PSize <= ((UInt32)1 << 30);
3023 } 3153 }
3024 3154
3155 UInt32 GetSize_Extract() const
3156 {
3157 return ExtractSize;
3158 }
3159
3025 void UpdateTotalSize(UInt32 &totalSize) 3160 void UpdateTotalSize(UInt32 &totalSize)
3026 { 3161 {
3027 UInt32 t = Pa + PSize; 3162 const UInt32 t = Pa + PSize;
3028 if (t > totalSize) 3163 if (totalSize < t)
3029 totalSize = t; 3164 totalSize = t;
3030 } 3165 }
3031}; 3166};
3032 3167
@@ -3050,6 +3185,7 @@ static const Byte kProps[] =
3050{ 3185{
3051 kpidPath, 3186 kpidPath,
3052 kpidSize, 3187 kpidSize,
3188 kpidPackSize,
3053 kpidVirtualSize, 3189 kpidVirtualSize,
3054 kpidCharacts, 3190 kpidCharacts,
3055 kpidOffset, 3191 kpidOffset,
@@ -3108,7 +3244,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
3108 prop = MultiByteToUnicodeString(name); 3244 prop = MultiByteToUnicodeString(name);
3109 break; 3245 break;
3110 } 3246 }
3111 case kpidSize: 3247 case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;
3112 case kpidPackSize: prop = (UInt64)item.PSize; break; 3248 case kpidPackSize: prop = (UInt64)item.PSize; break;
3113 case kpidVirtualSize: prop = (UInt64)item.VSize; break; 3249 case kpidVirtualSize: prop = (UInt64)item.VSize; break;
3114 case kpidOffset: prop = item.Pa; break; 3250 case kpidOffset: prop = item.Pa; break;
@@ -3168,13 +3304,13 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
3168{ 3304{
3169 COM_TRY_BEGIN 3305 COM_TRY_BEGIN
3170 Close(); 3306 Close();
3171 try 3307 // try
3172 { 3308 {
3173 if (Open2(inStream) != S_OK) 3309 if (Open2(inStream) != S_OK)
3174 return S_FALSE; 3310 return S_FALSE;
3175 _stream = inStream; 3311 _stream = inStream;
3176 } 3312 }
3177 catch(...) { return S_FALSE; } 3313 // catch(...) { return S_FALSE; }
3178 return S_OK; 3314 return S_OK;
3179 COM_TRY_END 3315 COM_TRY_END
3180} 3316}
@@ -3205,26 +3341,25 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
3205 UInt64 totalSize = 0; 3341 UInt64 totalSize = 0;
3206 UInt32 i; 3342 UInt32 i;
3207 for (i = 0; i < numItems; i++) 3343 for (i = 0; i < numItems; i++)
3208 totalSize += _items[allFilesMode ? i : indices[i]].PSize; 3344 totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();
3209 extractCallback->SetTotal(totalSize); 3345 RINOK(extractCallback->SetTotal(totalSize))
3210
3211 UInt64 currentTotalSize = 0;
3212
3213 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
3214 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
3215 3346
3216 CLocalProgress *lps = new CLocalProgress; 3347 CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
3217 CMyComPtr<ICompressProgressInfo> progress = lps; 3348 CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
3218 lps->Init(extractCallback, false); 3349 lps->Init(extractCallback, false);
3350 CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
3351 inStream->SetStream(_stream);
3219 3352
3220 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 3353 totalSize = 0;
3221 CMyComPtr<ISequentialInStream> inStream(streamSpec);
3222 streamSpec->SetStream(_stream);
3223 3354
3224 for (i = 0; i < numItems; i++) 3355 for (i = 0;; i++)
3225 { 3356 {
3226 lps->InSize = lps->OutSize = currentTotalSize; 3357 lps->InSize = lps->OutSize = totalSize;
3227 RINOK(lps->SetCur()) 3358 RINOK(lps->SetCur())
3359 if (i >= numItems)
3360 break;
3361 int opRes;
3362 {
3228 CMyComPtr<ISequentialOutStream> realOutStream; 3363 CMyComPtr<ISequentialOutStream> realOutStream;
3229 const Int32 askMode = testMode ? 3364 const Int32 askMode = testMode ?
3230 NExtract::NAskMode::kTest : 3365 NExtract::NAskMode::kTest :
@@ -3232,21 +3367,22 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
3232 const UInt32 index = allFilesMode ? i : indices[i]; 3367 const UInt32 index = allFilesMode ? i : indices[i];
3233 const CSection &item = _items[index]; 3368 const CSection &item = _items[index];
3234 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) 3369 RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
3235 currentTotalSize += item.PSize; 3370 const UInt32 size = item.GetSize_Extract();
3371 totalSize += size;
3236 3372
3237 if (!testMode && !realOutStream) 3373 if (!testMode && !realOutStream)
3238 continue; 3374 continue;
3239 RINOK(extractCallback->PrepareOperation(askMode)) 3375 RINOK(extractCallback->PrepareOperation(askMode))
3240 int res = NExtract::NOperationResult::kDataError;
3241
3242 RINOK(InStream_SeekSet(_stream, item.Pa)) 3376 RINOK(InStream_SeekSet(_stream, item.Pa))
3243 streamSpec->Init(item.PSize); 3377 inStream->Init(size);
3244 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) 3378 RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
3245 if (copyCoderSpec->TotalSize == item.PSize)
3246 res = NExtract::NOperationResult::kOK;
3247 3379
3248 realOutStream.Release(); 3380 opRes = (copyCoder->TotalSize == size) ?
3249 RINOK(extractCallback->SetOperationResult(res)) 3381 NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?
3382 NExtract::NOperationResult::kUnexpectedEnd :
3383 NExtract::NOperationResult::kDataError;
3384 }
3385 RINOK(extractCallback->SetOperationResult(opRes))
3250 } 3386 }
3251 return S_OK; 3387 return S_OK;
3252 COM_TRY_END 3388 COM_TRY_END
@@ -3256,7 +3392,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
3256{ 3392{
3257 COM_TRY_BEGIN 3393 COM_TRY_BEGIN
3258 const CSection &item = _items[index]; 3394 const CSection &item = _items[index];
3259 return CreateLimitedInStream(_stream, item.Pa, item.PSize, stream); 3395 return CreateLimitedInStream(_stream, item.Pa, item.GetSize_Extract(), stream);
3260 COM_TRY_END 3396 COM_TRY_END
3261} 3397}
3262 3398
diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp
index 5a80daa..b072880 100644
--- a/CPP/7zip/Archive/QcowHandler.cpp
+++ b/CPP/7zip/Archive/QcowHandler.cpp
@@ -11,6 +11,7 @@
11#include "../../Common/MyBuffer2.h" 11#include "../../Common/MyBuffer2.h"
12 12
13#include "../../Windows/PropVariant.h" 13#include "../../Windows/PropVariant.h"
14#include "../../Windows/PropVariantUtils.h"
14 15
15#include "../Common/RegisterArc.h" 16#include "../Common/RegisterArc.h"
16#include "../Common/StreamObjects.h" 17#include "../Common/StreamObjects.h"
@@ -20,8 +21,8 @@
20 21
21#include "HandlerCont.h" 22#include "HandlerCont.h"
22 23
23#define Get32(p) GetBe32(p) 24#define Get32(p) GetBe32a(p)
24#define Get64(p) GetBe64(p) 25#define Get64(p) GetBe64a(p)
25 26
26using namespace NWindows; 27using namespace NWindows;
27 28
@@ -32,9 +33,9 @@ static const Byte k_Signature[] = { 'Q', 'F', 'I', 0xFB, 0, 0, 0 };
32 33
33/* 34/*
34VA to PA maps: 35VA to PA maps:
35 high bits (L1) : : in L1 Table : the reference to L1 Table 36 high bits (L1) : : index in L1 (_dir) : _dir[high_index] points to Table.
36 mid bits (L2) : _numMidBits : in L2 Table : the reference to cluster 37 mid bits (L2) : _numMidBits : index in Table, Table[index] points to cluster start offset in arc file.
37 low bits : _clusterBits 38 low bits : _clusterBits : offset inside cluster.
38*/ 39*/
39 40
40Z7_class_CHandler_final: public CHandlerImg 41Z7_class_CHandler_final: public CHandlerImg
@@ -49,30 +50,27 @@ Z7_class_CHandler_final: public CHandlerImg
49 50
50 CObjArray2<UInt32> _dir; 51 CObjArray2<UInt32> _dir;
51 CAlignedBuffer _table; 52 CAlignedBuffer _table;
52 UInt64 _cacheCluster;
53 CByteBuffer _cache; 53 CByteBuffer _cache;
54 CByteBuffer _cacheCompressed; 54 CByteBuffer _cacheCompressed;
55 UInt64 _cacheCluster;
55 56
56 UInt64 _comprPos; 57 UInt64 _comprPos;
57 size_t _comprSize; 58 size_t _comprSize;
58 59
59 UInt64 _phySize; 60 bool _needCompression;
60
61 CBufInStream *_bufInStreamSpec;
62 CMyComPtr<ISequentialInStream> _bufInStream;
63
64 CBufPtrSeqOutStream *_bufOutStreamSpec;
65 CMyComPtr<ISequentialOutStream> _bufOutStream;
66
67 NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoderSpec;
68 CMyComPtr<ICompressCoder> _deflateDecoder;
69
70 bool _needDeflate;
71 bool _isArc; 61 bool _isArc;
72 bool _unsupported; 62 bool _unsupported;
63 Byte _compressionType;
64
65 UInt64 _phySize;
66
67 CMyComPtr2<ISequentialInStream, CBufInStream> _bufInStream;
68 CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> _bufOutStream;
69 CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> _deflateDecoder;
73 70
74 UInt32 _version; 71 UInt32 _version;
75 UInt32 _cryptMethod; 72 UInt32 _cryptMethod;
73 UInt64 _incompatFlags;
76 74
77 HRESULT Seek2(UInt64 offset) 75 HRESULT Seek2(UInt64 offset)
78 { 76 {
@@ -96,13 +94,11 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
96{ 94{
97 if (processedSize) 95 if (processedSize)
98 *processedSize = 0; 96 *processedSize = 0;
99
100 // printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size); 97 // printf("\nRead _virtPos = %6d size = %6d\n", (UInt32)_virtPos, size);
101
102 if (_virtPos >= _size) 98 if (_virtPos >= _size)
103 return S_OK; 99 return S_OK;
104 { 100 {
105 UInt64 rem = _size - _virtPos; 101 const UInt64 rem = _size - _virtPos;
106 if (size > rem) 102 if (size > rem)
107 size = (UInt32)rem; 103 size = (UInt32)rem;
108 if (size == 0) 104 if (size == 0)
@@ -115,47 +111,43 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
115 const size_t clusterSize = (size_t)1 << _clusterBits; 111 const size_t clusterSize = (size_t)1 << _clusterBits;
116 const size_t lowBits = (size_t)_virtPos & (clusterSize - 1); 112 const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);
117 { 113 {
118 size_t rem = clusterSize - lowBits; 114 const size_t rem = clusterSize - lowBits;
119 if (size > rem) 115 if (size > rem)
120 size = (UInt32)rem; 116 size = (UInt32)rem;
121 } 117 }
122
123 if (cluster == _cacheCluster) 118 if (cluster == _cacheCluster)
124 { 119 {
125 memcpy(data, _cache + lowBits, size); 120 memcpy(data, _cache + lowBits, size);
126 break; 121 break;
127 } 122 }
128 123
129 const UInt64 high = cluster >> _numMidBits; 124 const UInt64 high = cluster >> _numMidBits;
130 125
131 if (high < _dir.Size()) 126 if (high < _dir.Size())
132 { 127 {
133 const UInt32 tabl = _dir[(unsigned)high]; 128 const UInt32 tabl = _dir[(size_t)high];
134
135 if (tabl != kEmptyDirItem) 129 if (tabl != kEmptyDirItem)
136 { 130 {
137 const Byte *buffer = _table + ((size_t)tabl << (_numMidBits + 3));
138 const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1); 131 const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);
139 const Byte *p = (const Byte *)buffer + (midBits << 3); 132 const Byte *p = _table + ((((size_t)tabl << _numMidBits) + midBits) << 3);
140 UInt64 v = Get64(p); 133 UInt64 v = Get64(p);
141 134
142 if (v != 0) 135 if (v)
143 { 136 {
144 if ((v & _compressedFlag) != 0) 137 if (v & _compressedFlag)
145 { 138 {
146 if (_version <= 1) 139 if (_version <= 1)
147 return E_FAIL; 140 return E_FAIL;
148
149 /* 141 /*
150 the example of table record for 12-bit clusters (4KB uncompressed). 142 the example of table record for 12-bit clusters (4KB uncompressed):
151 2 bits : isCompressed status 143 2 bits : isCompressed status
152 4 bits : num_sectors_minus1; packSize = (num_sectors_minus1 + 1) * 512; 144 (4 == _clusterBits - 8) bits : (num_sectors - 1)
153 it uses one additional bit over unpacked cluster_bits 145 packSize = num_sectors * 512;
154 49 bits : offset of 512-sector 146 it uses one additional bit over unpacked cluster_bits.
155 9 bits : offset in 512-sector 147 (49 == 61 - _clusterBits) bits : offset of 512-byte sector
148 9 bits : offset in 512-byte sector
156 */ 149 */
157 150 const unsigned numOffsetBits = 62 - (_clusterBits - 8);
158 const unsigned numOffsetBits = (62 - (_clusterBits - 9 + 1));
159 const UInt64 offset = v & (((UInt64)1 << 62) - 1); 151 const UInt64 offset = v & (((UInt64)1 << 62) - 1);
160 const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9; 152 const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
161 UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9)); 153 UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));
@@ -167,7 +159,7 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
167 159
168 if (sectorOffset >= _comprPos && offset2inCache < _comprSize) 160 if (sectorOffset >= _comprPos && offset2inCache < _comprSize)
169 { 161 {
170 if (offset2inCache != 0) 162 if (offset2inCache)
171 { 163 {
172 _comprSize -= (size_t)offset2inCache; 164 _comprSize -= (size_t)offset2inCache;
173 memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize); 165 memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);
@@ -193,39 +185,34 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
193 const size_t dataSize3 = dataSize - _comprSize; 185 const size_t dataSize3 = dataSize - _comprSize;
194 size_t dataSize2 = dataSize3; 186 size_t dataSize2 = dataSize3;
195 // printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos); 187 // printf("\n\n=======\nReadStream = %6d _comprPos = %6d \n", (UInt32)dataSize2, (UInt32)_comprPos);
196 RINOK(ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2)) 188 const HRESULT hres = ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2);
197 _posInArc += dataSize2; 189 _posInArc += dataSize2;
190 RINOK(hres)
198 if (dataSize2 != dataSize3) 191 if (dataSize2 != dataSize3)
199 return E_FAIL; 192 return E_FAIL;
200 _comprSize += dataSize2; 193 _comprSize += dataSize2;
201 } 194 }
202 195
203 const size_t kSectorMask = (1 << 9) - 1; 196 const size_t kSectorMask = (1 << 9) - 1;
204 const size_t offsetInSector = ((size_t)offset & kSectorMask); 197 const size_t offsetInSector = (size_t)offset & kSectorMask;
205 _bufInStreamSpec->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector); 198 _bufInStream->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);
206
207 _cacheCluster = (UInt64)(Int64)-1; 199 _cacheCluster = (UInt64)(Int64)-1;
208 if (_cache.Size() < clusterSize) 200 if (_cache.Size() < clusterSize)
209 return E_FAIL; 201 return E_FAIL;
210 _bufOutStreamSpec->Init(_cache, clusterSize); 202 _bufOutStream->Init(_cache, clusterSize);
211
212 // Do we need to use smaller block than clusterSize for last cluster? 203 // Do we need to use smaller block than clusterSize for last cluster?
213 const UInt64 blockSize64 = clusterSize; 204 const UInt64 blockSize64 = clusterSize;
214 HRESULT res = _deflateDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL); 205 HRESULT res = _deflateDecoder.Interface()->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);
215
216 /* 206 /*
217 if (_bufOutStreamSpec->GetPos() != clusterSize) 207 if (_bufOutStreamSpec->GetPos() != clusterSize)
218 memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos()); 208 memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());
219 */ 209 */
220
221 if (res == S_OK) 210 if (res == S_OK)
222 if (!_deflateDecoderSpec->IsFinished() 211 if (!_deflateDecoder->IsFinished()
223 || _bufOutStreamSpec->GetPos() != clusterSize) 212 || _bufOutStream->GetPos() != clusterSize)
224 res = S_FALSE; 213 res = S_FALSE;
225
226 RINOK(res) 214 RINOK(res)
227 _cacheCluster = cluster; 215 _cacheCluster = cluster;
228
229 continue; 216 continue;
230 /* 217 /*
231 memcpy(data, _cache + lowBits, size); 218 memcpy(data, _cache + lowBits, size);
@@ -233,17 +220,17 @@ Z7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))
233 */ 220 */
234 } 221 }
235 222
236 // version 3 support zero clusters 223 // version_3 supports zero clusters
237 if (((UInt32)v & 511) != 1) 224 if (((UInt32)v & 511) != 1)
238 { 225 {
239 v &= (_compressedFlag - 1); 226 v &= _compressedFlag - 1;
240 v += lowBits; 227 v += lowBits;
241 if (v != _posInArc) 228 if (v != _posInArc)
242 { 229 {
243 // printf("\n%12I64x\n", v - _posInArc); 230 // printf("\n%12I64x\n", v - _posInArc);
244 RINOK(Seek2(v)) 231 RINOK(Seek2(v))
245 } 232 }
246 HRESULT res = Stream->Read(data, size, &size); 233 const HRESULT res = Stream->Read(data, size, &size);
247 _posInArc += size; 234 _posInArc += size;
248 _virtPos += size; 235 _virtPos += size;
249 if (processedSize) 236 if (processedSize)
@@ -274,13 +261,25 @@ static const Byte kProps[] =
274static const Byte kArcProps[] = 261static const Byte kArcProps[] =
275{ 262{
276 kpidClusterSize, 263 kpidClusterSize,
264 kpidSectorSize, // actually we need variable to show table size
265 kpidHeadersSize,
277 kpidUnpackVer, 266 kpidUnpackVer,
278 kpidMethod 267 kpidMethod,
268 kpidCharacts
279}; 269};
280 270
281IMP_IInArchive_Props 271IMP_IInArchive_Props
282IMP_IInArchive_ArcProps 272IMP_IInArchive_ArcProps
283 273
274static const CUInt32PCharPair g_IncompatFlags_Characts[] =
275{
276 { 0, "Dirty" },
277 { 1, "Corrupt" },
278 { 2, "External_Data_File" },
279 { 3, "Compression" },
280 { 4, "Extended_L2" }
281};
282
284Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 283Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
285{ 284{
286 COM_TRY_BEGIN 285 COM_TRY_BEGIN
@@ -290,28 +289,54 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
290 { 289 {
291 case kpidMainSubfile: prop = (UInt32)0; break; 290 case kpidMainSubfile: prop = (UInt32)0; break;
292 case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break; 291 case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;
293 case kpidPhySize: if (_phySize != 0) prop = _phySize; break; 292 case kpidSectorSize: prop = (UInt32)1 << (_numMidBits + 3); break;
293 case kpidHeadersSize: prop = _table.Size() + (UInt64)_dir.Size() * 8; break;
294 case kpidPhySize: if (_phySize) prop = _phySize; break;
294 case kpidUnpackVer: prop = _version; break; 295 case kpidUnpackVer: prop = _version; break;
295 296 case kpidCharacts:
297 {
298 if (_incompatFlags)
299 {
300 AString s ("incompatible: ");
301 // we need to show also high 32-bits.
302 s += FlagsToString(g_IncompatFlags_Characts,
303 Z7_ARRAY_SIZE(g_IncompatFlags_Characts), (UInt32)_incompatFlags);
304 prop = s;
305 }
306 break;
307 }
296 case kpidMethod: 308 case kpidMethod:
297 { 309 {
298 AString s; 310 AString s;
299 311
300 if (_needDeflate) 312 if (_compressionType)
301 s = "Deflate"; 313 {
314 if (_compressionType == 1)
315 s += "ZSTD";
316 else
317 {
318 s += "Compression:";
319 s.Add_UInt32(_compressionType);
320 }
321 }
322 else if (_needCompression)
323 s.Add_OptSpaced("Deflate");
302 324
303 if (_cryptMethod != 0) 325 if (_cryptMethod)
304 { 326 {
305 s.Add_Space_if_NotEmpty(); 327 s.Add_Space_if_NotEmpty();
306 if (_cryptMethod == 1) 328 if (_cryptMethod == 1)
307 s += "AES"; 329 s += "AES";
330 if (_cryptMethod == 2)
331 s += "LUKS";
308 else 332 else
333 {
334 s += "Encryption:";
309 s.Add_UInt32(_cryptMethod); 335 s.Add_UInt32(_cryptMethod);
336 }
310 } 337 }
311
312 if (!s.IsEmpty()) 338 if (!s.IsEmpty())
313 prop = s; 339 prop = s;
314
315 break; 340 break;
316 } 341 }
317 342
@@ -321,9 +346,9 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
321 if (!_isArc) v |= kpv_ErrorFlags_IsNotArc; 346 if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;
322 if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod; 347 if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;
323 // if (_headerError) v |= kpv_ErrorFlags_HeadersError; 348 // if (_headerError) v |= kpv_ErrorFlags_HeadersError;
324 if (!Stream && v == 0 && _isArc) 349 if (!Stream && v == 0)
325 v = kpv_ErrorFlags_HeadersError; 350 v = kpv_ErrorFlags_HeadersError;
326 if (v != 0) 351 if (v)
327 prop = v; 352 prop = v;
328 break; 353 break;
329 } 354 }
@@ -355,76 +380,91 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIAN
355 380
356HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) 381HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
357{ 382{
358 const unsigned kHeaderSize = 18 * 4; 383 UInt64 buf64[0x70 / 8];
359 Byte buf[kHeaderSize]; 384 RINOK(ReadStream_FALSE(stream, buf64, sizeof(buf64)))
360 RINOK(ReadStream_FALSE(stream, buf, kHeaderSize)) 385 const void *buf = (const void *)buf64;
361 386 // signature: { 'Q', 'F', 'I', 0xFB }
362 if (memcmp(buf, k_Signature, 4) != 0) 387 if (*(const UInt32 *)buf != Z7_CONV_BE_TO_NATIVE_CONST32(0x514649fb))
363 return S_FALSE; 388 return S_FALSE;
364 389 _version = Get32((const Byte *)(const void *)buf64 + 4);
365 _version = Get32(buf + 4);
366 if (_version < 1 || _version > 3) 390 if (_version < 1 || _version > 3)
367 return S_FALSE; 391 return S_FALSE;
368 392
369 const UInt64 backOffset = Get64(buf + 8); 393 const UInt64 k_UncompressedSize_MAX = (UInt64)1 << 60;
370 // UInt32 backSize = Get32(buf + 0x10); 394 const UInt64 k_CompressedSize_MAX = (UInt64)1 << 60;
371 395
372 UInt64 l1Offset; 396 _size = Get64((const Byte *)(const void *)buf64 + 0x18);
373 UInt32 l1Size; 397 if (_size > k_UncompressedSize_MAX)
398 return S_FALSE;
399 size_t l1Size;
400 UInt32 headerSize;
374 401
375 if (_version == 1) 402 if (_version == 1)
376 { 403 {
377 // _mTime = Get32(buf + 0x14); // is unused im most images 404 // _mTime = Get32((const Byte *)(const void *)buf64 + 0x14); // is unused in most images
378 _size = Get64(buf + 0x18); 405 _clusterBits = ((const Byte *)(const void *)buf64)[0x20];
379 _clusterBits = buf[0x20]; 406 _numMidBits = ((const Byte *)(const void *)buf64)[0x21];
380 _numMidBits = buf[0x21];
381 if (_clusterBits < 9 || _clusterBits > 30) 407 if (_clusterBits < 9 || _clusterBits > 30)
382 return S_FALSE; 408 return S_FALSE;
383 if (_numMidBits < 1 || _numMidBits > 28) 409 if (_numMidBits < 1 || _numMidBits > 28)
384 return S_FALSE; 410 return S_FALSE;
385 _cryptMethod = Get32(buf + 0x24); 411 _cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x24);
386 l1Offset = Get64(buf + 0x28); 412 const unsigned numBits2 = _clusterBits + _numMidBits;
387 if (l1Offset < 0x30)
388 return S_FALSE;
389 const unsigned numBits2 = (_clusterBits + _numMidBits);
390 const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2; 413 const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;
391 if (l1Size64 > ((UInt32)1 << 31)) 414 if (l1Size64 > ((UInt32)1 << 31))
392 return S_FALSE; 415 return S_FALSE;
393 l1Size = (UInt32)l1Size64; 416 l1Size = (size_t)l1Size64;
417 headerSize = 0x30;
394 } 418 }
395 else 419 else
396 { 420 {
397 _clusterBits = Get32(buf + 0x14); 421 _clusterBits = Get32((const Byte *)(const void *)buf64 + 0x14);
398 if (_clusterBits < 9 || _clusterBits > 30) 422 if (_clusterBits < 9 || _clusterBits > 30)
399 return S_FALSE; 423 return S_FALSE;
400 _numMidBits = _clusterBits - 3; 424 _numMidBits = _clusterBits - 3;
401 _size = Get64(buf + 0x18); 425 _cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x20);
402 _cryptMethod = Get32(buf + 0x20); 426 l1Size = Get32((const Byte *)(const void *)buf64 + 0x24);
403 l1Size = Get32(buf + 0x24); 427 headerSize = 0x48;
404 l1Offset = Get64(buf + 0x28); // must be aligned for cluster 428 if (_version >= 3)
405 429 {
406 const UInt64 refOffset = Get64(buf + 0x30); // must be aligned for cluster 430 _incompatFlags = Get64((const Byte *)(const void *)buf64 + 0x48);
407 const UInt32 refClusters = Get32(buf + 0x38); 431 // const UInt64 CompatFlags = Get64((const Byte *)(const void *)buf64 + 0x50);
408 432 // const UInt64 AutoClearFlags = Get64((const Byte *)(const void *)buf64 + 0x58);
409 // UInt32 numSnapshots = Get32(buf + 0x3C); 433 // const UInt32 RefCountOrder = Get32((const Byte *)(const void *)buf64 + 0x60);
410 // UInt64 snapshotsOffset = Get64(buf + 0x40); // must be aligned for cluster 434 headerSize = 0x68;
435 const UInt32 headerSize2 = Get32((const Byte *)(const void *)buf64 + 0x64);
436 if (headerSize2 > (1u << 30))
437 return S_FALSE;
438 if (headerSize < headerSize2)
439 headerSize = headerSize2;
440 if (headerSize2 >= 0x68 + 1)
441 _compressionType = ((const Byte *)(const void *)buf64)[0x68];
442 }
443
444 const UInt64 refOffset = Get64((const Byte *)(const void *)buf64 + 0x30); // must be aligned for cluster
445 const UInt32 refClusters = Get32((const Byte *)(const void *)buf64 + 0x38);
446 // UInt32 numSnapshots = Get32((const Byte *)(const void *)buf64 + 0x3C);
447 // UInt64 snapshotsOffset = Get64((const Byte *)(const void *)buf64 + 0x40); // must be aligned for cluster
411 /* 448 /*
412 if (numSnapshots != 0) 449 if (numSnapshots)
413 return S_FALSE; 450 return S_FALSE;
414 */ 451 */
415 452 if (refClusters)
416 if (refClusters != 0)
417 { 453 {
418 const size_t numBytes = refClusters << _clusterBits; 454 if (refOffset > k_CompressedSize_MAX)
455 return S_FALSE;
456 const UInt64 numBytes = (UInt64)refClusters << _clusterBits;
457 const UInt64 end = refOffset + numBytes;
458 if (end > k_CompressedSize_MAX)
459 return S_FALSE;
419 /* 460 /*
420 CByteBuffer refs; 461 CByteBuffer refs;
421 refs.Alloc(numBytes); 462 refs.Alloc(numBytes);
422 RINOK(InStream_SeekSet(stream, refOffset)) 463 RINOK(InStream_SeekSet(stream, refOffset))
423 RINOK(ReadStream_FALSE(stream, refs, numBytes)); 464 RINOK(ReadStream_FALSE(stream, refs, numBytes));
424 */ 465 */
425 const UInt64 end = refOffset + numBytes;
426 if (_phySize < end) 466 if (_phySize < end)
427 _phySize = end; 467 _phySize = end;
428 /* 468 /*
429 for (size_t i = 0; i < numBytes; i += 2) 469 for (size_t i = 0; i < numBytes; i += 2)
430 { 470 {
@@ -436,48 +476,76 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
436 } 476 }
437 } 477 }
438 478
439 _isArc = true; 479 const UInt64 l1Offset = Get64((const Byte *)(const void *)buf64 + 0x28); // must be aligned for cluster ?
480 if (l1Offset < headerSize || l1Offset > k_CompressedSize_MAX)
481 return S_FALSE;
482 if (_phySize < headerSize)
483 _phySize = headerSize;
440 484
441 if (backOffset != 0) 485 _isArc = true;
442 { 486 {
443 _unsupported = true; 487 const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8);
444 return S_FALSE; 488 // UInt32 backSize = Get32((const Byte *)(const void *)buf64 + 0x10);
489 if (backOffset)
490 {
491 _unsupported = true;
492 return S_FALSE;
493 }
445 } 494 }
446 495
447 const size_t clusterSize = (size_t)1 << _clusterBits; 496 UInt64 fileSize = 0;
497 RINOK(InStream_GetSize_SeekToBegin(stream, fileSize))
448 498
449 CByteBuffer table; 499 const size_t clusterSize = (size_t)1 << _clusterBits;
500 const size_t t1SizeBytes = (size_t)l1Size << 3;
450 { 501 {
451 const size_t t1SizeBytes = (size_t)l1Size << 3; 502 const UInt64 end = l1Offset + t1SizeBytes;
452 if ((t1SizeBytes >> 3) != l1Size) 503 if (end > k_CompressedSize_MAX)
453 return S_FALSE; 504 return S_FALSE;
454 table.Alloc(t1SizeBytes); 505 // we need to use align end for empty qcow files
455 RINOK(InStream_SeekSet(stream, l1Offset)) 506 // some files has no cluster alignment padding at the end
456 RINOK(ReadStream_FALSE(stream, table, t1SizeBytes)) 507 // but has sector alignment
457 508 // end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
458 { 509 if (_phySize < end)
459 UInt64 end = l1Offset + t1SizeBytes;
460 // we need to uses align end for empty qcow files
461 end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;
462 if (_phySize < end)
463 _phySize = end; 510 _phySize = end;
511 if (end > fileSize)
512 return S_FALSE;
513 if (_phySize < fileSize)
514 {
515 const UInt64 end2 = (end + 511) & ~(UInt64)511;
516 if (end2 == fileSize)
517 _phySize = end2;
464 } 518 }
465 } 519 }
520 CObjArray<UInt64> table64(l1Size);
521 {
522 // if ((t1SizeBytes >> 3) != l1Size) return S_FALSE;
523 RINOK(InStream_SeekSet(stream, l1Offset))
524 RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes))
525 }
466 526
467 _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62); 527 _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);
468 const UInt64 offsetMask = _compressedFlag - 1; 528 const UInt64 offsetMask = _compressedFlag - 1;
529 const size_t midSize = (size_t)1 << (_numMidBits + 3);
530 size_t numTables = 0;
531 size_t i;
469 532
470 UInt32 numTables = 0;
471 UInt32 i;
472
473 for (i = 0; i < l1Size; i++) 533 for (i = 0; i < l1Size; i++)
474 { 534 {
475 const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; 535 const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
476 if (v != 0) 536 if (!v)
477 numTables++; 537 continue;
538 numTables++;
539 const UInt64 end = v + midSize;
540 if (end > k_CompressedSize_MAX)
541 return S_FALSE;
542 if (_phySize < end)
543 _phySize = end;
544 if (end > fileSize)
545 return S_FALSE;
478 } 546 }
479 547
480 if (numTables != 0) 548 if (numTables)
481 { 549 {
482 const size_t size = (size_t)numTables << (_numMidBits + 3); 550 const size_t size = (size_t)numTables << (_numMidBits + 3);
483 if (size >> (_numMidBits + 3) != numTables) 551 if (size >> (_numMidBits + 3) != numTables)
@@ -485,48 +553,38 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
485 _table.Alloc(size); 553 _table.Alloc(size);
486 if (!_table.IsAllocated()) 554 if (!_table.IsAllocated())
487 return E_OUTOFMEMORY; 555 return E_OUTOFMEMORY;
556 if (openCallback)
557 {
558 const UInt64 totalBytes = size;
559 RINOK(openCallback->SetTotal(NULL, &totalBytes))
560 }
488 } 561 }
489 562
490 _dir.SetSize(l1Size); 563 _dir.SetSize((unsigned)l1Size);
491 564
492 UInt32 curTable = 0; 565 UInt32 curTable = 0;
493 566
494 if (openCallback)
495 {
496 const UInt64 totalBytes = (UInt64)numTables << (_numMidBits + 3);
497 RINOK(openCallback->SetTotal(NULL, &totalBytes))
498 }
499
500 for (i = 0; i < l1Size; i++) 567 for (i = 0; i < l1Size; i++)
501 { 568 {
502 Byte *buf2; 569 Byte *buf2;
503 const size_t midSize = (size_t)1 << (_numMidBits + 3);
504
505 { 570 {
506 const UInt64 v = Get64((const Byte *)table + (size_t)i * 8) & offsetMask; 571 const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;
507 if (v == 0) 572 if (v == 0)
508 { 573 {
509 _dir[i] = kEmptyDirItem; 574 _dir[i] = kEmptyDirItem;
510 continue; 575 continue;
511 } 576 }
512
513 _dir[i] = curTable; 577 _dir[i] = curTable;
514 const size_t tableOffset = ((size_t)curTable << (_numMidBits + 3)); 578 const size_t tableOffset = (size_t)curTable << (_numMidBits + 3);
515 buf2 = (Byte *)_table + tableOffset; 579 buf2 = (Byte *)_table + tableOffset;
516 curTable++; 580 curTable++;
517
518 if (openCallback && (tableOffset & 0xFFFFF) == 0) 581 if (openCallback && (tableOffset & 0xFFFFF) == 0)
519 { 582 {
520 const UInt64 numBytes = tableOffset; 583 const UInt64 numBytes = tableOffset;
521 RINOK(openCallback->SetCompleted(NULL, &numBytes)) 584 RINOK(openCallback->SetCompleted(NULL, &numBytes))
522 } 585 }
523
524 RINOK(InStream_SeekSet(stream, v)) 586 RINOK(InStream_SeekSet(stream, v))
525 RINOK(ReadStream_FALSE(stream, buf2, midSize)) 587 RINOK(ReadStream_FALSE(stream, buf2, midSize))
526
527 const UInt64 end = v + midSize;
528 if (_phySize < end)
529 _phySize = end;
530 } 588 }
531 589
532 for (size_t k = 0; k < midSize; k += 8) 590 for (size_t k = 0; k < midSize; k += 8)
@@ -537,33 +595,30 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
537 UInt64 offset = v & offsetMask; 595 UInt64 offset = v & offsetMask;
538 size_t dataSize = clusterSize; 596 size_t dataSize = clusterSize;
539 597
540 if ((v & _compressedFlag) != 0) 598 if (v & _compressedFlag)
541 { 599 {
542 if (_version <= 1) 600 if (_version <= 1)
543 { 601 {
544 unsigned numOffsetBits = (63 - _clusterBits); 602 const unsigned numOffsetBits = 63 - _clusterBits;
545 dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9; 603 dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
546 offset &= ((UInt64)1 << numOffsetBits) - 1; 604 offset &= ((UInt64)1 << numOffsetBits) - 1;
547 dataSize = 0; 605 dataSize = 0; // why ?
548 // offset >>= 9; 606 // offset &= ~(((UInt64)1 << 9) - 1);
549 // offset <<= 9;
550 } 607 }
551 else 608 else
552 { 609 {
553 unsigned numOffsetBits = (62 - (_clusterBits - 8)); 610 const unsigned numOffsetBits = 62 - (_clusterBits - 8);
554 dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9; 611 dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;
555 offset &= ((UInt64)1 << numOffsetBits) - 1; 612 offset &= ((UInt64)1 << numOffsetBits) - (1 << 9);
556 offset >>= 9;
557 offset <<= 9;
558 } 613 }
559 _needDeflate = true; 614 _needCompression = true;
560 } 615 }
561 else 616 else
562 { 617 {
563 UInt32 low = (UInt32)v & 511; 618 const UInt32 low = (UInt32)v & 511;
564 if (low != 0) 619 if (low)
565 { 620 {
566 // version 3 support zero clusters 621 // version_3 supports zero clusters
567 if (_version < 3 || low != 1) 622 if (_version < 3 || low != 1)
568 { 623 {
569 _unsupported = true; 624 _unsupported = true;
@@ -574,17 +629,18 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)
574 629
575 const UInt64 end = offset + dataSize; 630 const UInt64 end = offset + dataSize;
576 if (_phySize < end) 631 if (_phySize < end)
577 _phySize = end; 632 _phySize = end;
578 } 633 }
579 } 634 }
580 635
581 if (curTable != numTables) 636 if (curTable != numTables)
582 return E_FAIL; 637 return E_FAIL;
583 638
584 if (_cryptMethod != 0) 639 if (_cryptMethod)
585 _unsupported = true; 640 _unsupported = true;
586 641 if (_needCompression && _version <= 1) // that case was not implemented
587 if (_needDeflate && _version <= 1) // that case was not implemented 642 _unsupported = true;
643 if (_compressionType)
588 _unsupported = true; 644 _unsupported = true;
589 645
590 Stream = stream; 646 Stream = stream;
@@ -596,16 +652,21 @@ Z7_COM7F_IMF(CHandler::Close())
596{ 652{
597 _table.Free(); 653 _table.Free();
598 _dir.Free(); 654 _dir.Free();
655 // _cache.Free();
656 // _cacheCompressed.Free();
599 _phySize = 0; 657 _phySize = 0;
600 658
601 _cacheCluster = (UInt64)(Int64)-1; 659 _cacheCluster = (UInt64)(Int64)-1;
602 _comprPos = 0; 660 _comprPos = 0;
603 _comprSize = 0; 661 _comprSize = 0;
604 _needDeflate = false;
605 662
663 _needCompression = false;
606 _isArc = false; 664 _isArc = false;
607 _unsupported = false; 665 _unsupported = false;
608 666
667 _compressionType = 0;
668 _incompatFlags = 0;
669
609 // CHandlerImg: 670 // CHandlerImg:
610 Clear_HandlerImg_Vars(); 671 Clear_HandlerImg_Vars();
611 Stream.Release(); 672 Stream.Release();
@@ -617,39 +678,20 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **strea
617{ 678{
618 COM_TRY_BEGIN 679 COM_TRY_BEGIN
619 *stream = NULL; 680 *stream = NULL;
620 681 if (_unsupported || !Stream)
621 if (_unsupported)
622 return S_FALSE; 682 return S_FALSE;
623 683 if (_needCompression)
624 if (_needDeflate)
625 { 684 {
626 if (_version <= 1) 685 if (_version <= 1 || _compressionType)
627 return S_FALSE; 686 return S_FALSE;
628 687 _bufInStream.Create_if_Empty();
629 if (!_bufInStream) 688 _bufOutStream.Create_if_Empty();
630 { 689 _deflateDecoder.Create_if_Empty();
631 _bufInStreamSpec = new CBufInStream; 690 _deflateDecoder->Set_NeedFinishInput(true);
632 _bufInStream = _bufInStreamSpec;
633 }
634
635 if (!_bufOutStream)
636 {
637 _bufOutStreamSpec = new CBufPtrSeqOutStream();
638 _bufOutStream = _bufOutStreamSpec;
639 }
640
641 if (!_deflateDecoder)
642 {
643 _deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder();
644 _deflateDecoder = _deflateDecoderSpec;
645 _deflateDecoderSpec->Set_NeedFinishInput(true);
646 }
647
648 const size_t clusterSize = (size_t)1 << _clusterBits; 691 const size_t clusterSize = (size_t)1 << _clusterBits;
649 _cache.AllocAtLeast(clusterSize); 692 _cache.AllocAtLeast(clusterSize);
650 _cacheCompressed.AllocAtLeast(clusterSize * 2); 693 _cacheCompressed.AllocAtLeast(clusterSize * 2);
651 } 694 }
652
653 CMyComPtr<ISequentialInStream> streamTemp = this; 695 CMyComPtr<ISequentialInStream> streamTemp = this;
654 RINOK(InitAndSeek()) 696 RINOK(InitAndSeek())
655 *stream = streamTemp.Detach(); 697 *stream = streamTemp.Detach();
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
index b786f3e..34615c2 100644
--- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp
+++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp
@@ -1456,7 +1456,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
1456 } 1456 }
1457 if (arcInfo->Locator.Is_Recovery()) 1457 if (arcInfo->Locator.Is_Recovery())
1458 { 1458 {
1459 s += "Recovery:"; 1459 s.Add_OptSpaced("Recovery:");
1460 s.Add_UInt64(arcInfo->Locator.Recovery); 1460 s.Add_UInt64(arcInfo->Locator.Recovery);
1461 } 1461 }
1462 } 1462 }
diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
index b2742b7..bc047b7 100644
--- a/CPP/7zip/Archive/Zip/ZipUpdate.cpp
+++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp
@@ -1755,16 +1755,17 @@ HRESULT CCacheOutStream::FlushFromCache(size_t size)
1755 PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size)); 1755 PRF(printf("\n-- CCacheOutStream::FlushFromCache %u\n", (unsigned)size));
1756 if (_hres != S_OK) 1756 if (_hres != S_OK)
1757 return _hres; 1757 return _hres;
1758 if (size == 0 || _cachedSize == 0) 1758 if (size > _cachedSize)
1759 size = _cachedSize;
1760 // (size <= _cachedSize)
1761 if (size == 0)
1759 return S_OK; 1762 return S_OK;
1760 RINOK(SeekPhy(_cachedPos)) 1763 RINOK(SeekPhy(_cachedPos))
1761 for (;;) 1764 for (;;)
1762 { 1765 {
1763 // (_phyPos == _cachedPos) 1766 // (_phyPos == _cachedPos)
1764 const size_t pos = (size_t)_cachedPos & kCacheMask; 1767 const size_t pos = (size_t)_cachedPos & kCacheMask;
1765 size_t cur = kCacheSize - pos; 1768 const size_t cur = MyMin(kCacheSize - pos, size);
1766 cur = MyMin(cur, _cachedSize);
1767 cur = MyMin(cur, size);
1768 _hres = SetRestriction_ForWrite(cur); 1769 _hres = SetRestriction_ForWrite(cur);
1769 RINOK(_hres) 1770 RINOK(_hres)
1770 PRF(printf("\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\n", (unsigned)_phyPos, (unsigned)cur)); 1771 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)
1776 _cachedPos += cur; 1777 _cachedPos += cur;
1777 _cachedSize -= cur; 1778 _cachedSize -= cur;
1778 size -= cur; 1779 size -= cur;
1779 if (size == 0 || _cachedSize == 0) 1780 if (size == 0)
1780 return S_OK; 1781 return S_OK;
1781 } 1782 }
1782} 1783}
@@ -1964,7 +1965,11 @@ Z7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))
1964 // so we reduce cache 1965 // so we reduce cache
1965 _cachedSize = (size_t)offset; 1966 _cachedSize = (size_t)offset;
1966 if (_phySize <= newSize) 1967 if (_phySize <= newSize)
1967 return S_OK; // _phySize will be restored later after cache flush 1968 {
1969 // _phySize will be restored later after cache flush
1970 _virtSize = newSize;
1971 return S_OK;
1972 }
1968 // (_phySize > newSize) 1973 // (_phySize > newSize)
1969 // so we must reduce phyStream size to (newSize) or to (_cachedPos) 1974 // so we must reduce phyStream size to (newSize) or to (_cachedPos)
1970 // newPhySize = _cachedPos; // optional reduce to _cachedPos 1975 // newPhySize = _cachedPos; // optional reduce to _cachedPos
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp
index 87a2df4..e1ca846 100644
--- a/CPP/7zip/UI/Common/Bench.cpp
+++ b/CPP/7zip/UI/Common/Bench.cpp
@@ -3713,7 +3713,7 @@ HRESULT Bench(
3713 } 3713 }
3714 */ 3714 */
3715 3715
3716 bool ramSize_Defined = NSystem::GetRamSize(ramSize); 3716 const bool ramSize_Defined = NSystem::GetRamSize(ramSize);
3717 3717
3718 UInt32 numThreadsSpecified = numCPUs; 3718 UInt32 numThreadsSpecified = numCPUs;
3719 bool needSetComplexity = false; 3719 bool needSetComplexity = false;
@@ -4002,16 +4002,29 @@ HRESULT Bench(
4002 } 4002 }
4003 } 4003 }
4004 4004
4005 if (numThreadsSpecified >= 2)
4006 if (printCallback || freqCallback) 4005 if (printCallback || freqCallback)
4006 for (unsigned test = 0; test < 3; test++)
4007 { 4007 {
4008 if (numThreadsSpecified < 2)
4009 {
4010 // if (test == 1)
4011 break;
4012 }
4013 if (test == 2 && numThreadsSpecified <= numCPUs)
4014 break;
4008 if (printCallback) 4015 if (printCallback)
4009 printCallback->NewLine(); 4016 printCallback->NewLine();
4010 4017
4011 /* it can show incorrect frequency for HT threads. 4018 /* it can show incorrect frequency for HT threads. */
4012 so we reduce freq test to (numCPUs / 2) */
4013 4019
4014 UInt32 numThreads = (numThreadsSpecified >= numCPUs / 2 ? numCPUs / 2 : numThreadsSpecified); 4020 UInt32 numThreads = numThreadsSpecified;
4021 if (test < 2)
4022 {
4023 if (numThreads >= numCPUs)
4024 numThreads = numCPUs;
4025 if (test == 0)
4026 numThreads /= 2;
4027 }
4015 if (numThreads < 1) 4028 if (numThreads < 1)
4016 numThreads = 1; 4029 numThreads = 1;
4017 4030
diff --git a/CPP/7zip/UI/Common/PropIDUtils.cpp b/CPP/7zip/UI/Common/PropIDUtils.cpp
index 0b1357f..d73680b 100644
--- a/CPP/7zip/UI/Common/PropIDUtils.cpp
+++ b/CPP/7zip/UI/Common/PropIDUtils.cpp
@@ -21,8 +21,8 @@
21 21
22using namespace NWindows; 22using namespace NWindows;
23 23
24static const unsigned kNumWinAtrribFlags = 21; 24static const unsigned kNumWinAtrribFlags = 30;
25static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU"; 25static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B";
26 26
27/* 27/*
28FILE_ATTRIBUTE_ 28FILE_ATTRIBUTE_
@@ -48,8 +48,9 @@ FILE_ATTRIBUTE_
4818 RECALL_ON_OPEN or EA 4818 RECALL_ON_OPEN or EA
4919 PINNED 4919 PINNED
5020 UNPINNED 5020 UNPINNED
5121 STRICTLY_SEQUENTIAL 5121 STRICTLY_SEQUENTIAL (10.0.16267)
5222 RECALL_ON_DATA_ACCESS 5222 RECALL_ON_DATA_ACCESS
5329 STRICTLY_SEQUENTIAL (10.0.17134+) (SMR Blob)
53*/ 54*/
54 55
55 56
@@ -107,10 +108,10 @@ void ConvertWinAttribToString(char *s, UInt32 wa) throw()
107 108
108 for (unsigned i = 0; i < kNumWinAtrribFlags; i++) 109 for (unsigned i = 0; i < kNumWinAtrribFlags; i++)
109 { 110 {
110 UInt32 flag = (1 << i); 111 const UInt32 flag = (UInt32)1 << i;
111 if ((wa & flag) != 0) 112 if (wa & flag)
112 { 113 {
113 char c = g_WinAttribChars[i]; 114 const char c = g_WinAttribChars[i];
114 if (c != '.') 115 if (c != '.')
115 { 116 {
116 wa &= ~flag; 117 wa &= ~flag;
diff --git a/CPP/7zip/UI/Common/Update.cpp b/CPP/7zip/UI/Common/Update.cpp
index 978630e..ed48605 100644
--- a/CPP/7zip/UI/Common/Update.cpp
+++ b/CPP/7zip/UI/Common/Update.cpp
@@ -1606,7 +1606,23 @@ HRESULT UpdateArchive(
1606 1606
1607 if (!MyMoveFile(tempPath, us2fs(arcPath))) 1607 if (!MyMoveFile(tempPath, us2fs(arcPath)))
1608 { 1608 {
1609 errorInfo.SetFromLastError("cannot move the file", tempPath); 1609 errorInfo.SystemError = ::GetLastError();
1610 errorInfo.Message = "cannot move the file";
1611 if (errorInfo.SystemError == ERROR_INVALID_PARAMETER)
1612 {
1613 NFind::CFileInfo fi;
1614 if (fi.Find(tempPath) &&
1615 fi.Size > (UInt32)(Int32)-1)
1616 {
1617 // bool isFsDetected = false;
1618 // if (NSystem::Is_File_LimitedBy_4GB(us2fs(arcPath), isFsDetected) || !isFsDetected)
1619 {
1620 errorInfo.Message.Add_LF();
1621 errorInfo.Message += "Archive file size exceeds 4 GB";
1622 }
1623 }
1624 }
1625 errorInfo.FileNames.Add(tempPath);
1610 errorInfo.FileNames.Add(us2fs(arcPath)); 1626 errorInfo.FileNames.Add(us2fs(arcPath));
1611 return errorInfo.Get_HRESULT_Error(); 1627 return errorInfo.Get_HRESULT_Error();
1612 } 1628 }
diff --git a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
index 376fbf3..f59d4c1 100644
--- a/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
+++ b/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp
@@ -924,11 +924,11 @@ HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
924 } 924 }
925 else 925 else
926 { 926 {
927 NumArcsWithError++; 927 // we don't update NumArcsWithError, if error is not related to archive data.
928 if (result == E_ABORT 928 if (result == E_ABORT
929 || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL) 929 || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL))
930 )
931 return result; 930 return result;
931 NumArcsWithError++;
932 932
933 if (_se) 933 if (_se)
934 { 934 {
diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp
index d79bab1..fab3493 100644
--- a/CPP/7zip/UI/Explorer/ContextMenu.cpp
+++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp
@@ -534,7 +534,8 @@ bool FindExt(const char *p, const UString &name, CStringFinder &finder);
534bool FindExt(const char *p, const UString &name, CStringFinder &finder) 534bool FindExt(const char *p, const UString &name, CStringFinder &finder)
535{ 535{
536 const int dotPos = name.ReverseFind_Dot(); 536 const int dotPos = name.ReverseFind_Dot();
537 if (dotPos < 0 || dotPos == (int)name.Len() - 1) 537 int len = (int)name.Len() - (dotPos + 1);
538 if (len == 0 || len > 32 || dotPos < 0)
538 return false; 539 return false;
539 return finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1)); 540 return finder.FindWord_In_LowCaseAsciiList_NoCase(p, name.Ptr(dotPos + 1));
540} 541}
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
index 446f6de..685ac70 100644
--- a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
@@ -387,8 +387,8 @@ Z7_COM7F_IMF(CAltStreamsFolder::WasChanged(Int32 *wasChanged))
387 return S_OK; 387 return S_OK;
388 } 388 }
389 389
390 DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0); 390 const DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
391 bool wasChangedLoc = (waitResult == WAIT_OBJECT_0); 391 const bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
392 if (wasChangedLoc) 392 if (wasChangedLoc)
393 { 393 {
394 _findChangeNotification.FindNext(); 394 _findChangeNotification.FindNext();
@@ -666,16 +666,10 @@ Z7_COM7F_IMF(CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID
666Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) 666Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
667{ 667{
668 const CAltStream &ss = Streams[index]; 668 const CAltStream &ss = Streams[index];
669 *iconIndex = 0; 669 return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
670 int iconIndexTemp; 670 _pathPrefix + us2fs(ss.Name),
671 if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name), 671 FILE_ATTRIBUTE_ARCHIVE,
672 0 // fi.Attrib 672 iconIndex);
673 , iconIndexTemp) != 0)
674 {
675 *iconIndex = iconIndexTemp;
676 return S_OK;
677 }
678 return GetLastError_noZero_HRESULT();
679} 673}
680 674
681/* 675/*
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
index d049fc9..06c2e8b 100644
--- a/CPP/7zip/UI/FileManager/App.cpp
+++ b/CPP/7zip/UI/FileManager/App.cpp
@@ -782,6 +782,7 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex)
782 if (useSrcPanel) 782 if (useSrcPanel)
783 { 783 {
784 CCopyToOptions options; 784 CCopyToOptions options;
785 // options.src_Is_IO_FS_Folder = useFullItemPaths;
785 options.folder = useTemp ? fs2us(tempDirPrefix) : destPath; 786 options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
786 options.moveMode = move; 787 options.moveMode = move;
787 options.includeAltStreams = true; 788 options.includeAltStreams = true;
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
index 6464ed8..b12d8e8 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -208,8 +208,8 @@ bool CBrowseDialog::OnInit()
208 _filterCombo.SetCurSel(FilterIndex); 208 _filterCombo.SetCurSel(FilterIndex);
209 } 209 }
210 210
211 _list.SetImageList(GetSysImageList(true), LVSIL_SMALL); 211 _list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
212 _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL); 212 _list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
213 213
214 _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100); 214 _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
215 _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100); 215 _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
@@ -690,19 +690,21 @@ HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selected
690 #ifndef UNDER_CE 690 #ifndef UNDER_CE
691 if (isDrive) 691 if (isDrive)
692 { 692 {
693 if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0) 693 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
694 item.iImage = 0; 694 fi.Name + FCHAR_PATH_SEPARATOR,
695 FILE_ATTRIBUTE_DIRECTORY);
695 } 696 }
696 else 697 else
697 #endif 698 #endif
698 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); 699 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
699 if (item.iImage < 0) 700 if (item.iImage < 0)
700 item.iImage = 0; 701 item.iImage = 0;
701 _list.InsertItem(&item); 702 _list.InsertItem(&item);
702 wchar_t s[64]; 703 wchar_t s[64];
703 { 704 {
704 s[0] = 0; 705 s[0] = 0;
705 ConvertUtcFileTimeToString(fi.MTime, s, 706 if (!FILETIME_IsZero(fi.MTime))
707 ConvertUtcFileTimeToString(fi.MTime, s,
706 #ifndef UNDER_CE 708 #ifndef UNDER_CE
707 kTimestampPrintLevel_MIN 709 kTimestampPrintLevel_MIN
708 #else 710 #else
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp
index 4bb8a34..ee98ab4 100644
--- a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp
+++ b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp
@@ -356,8 +356,8 @@ bool CBrowseDialog2::OnInit()
356#endif 356#endif
357 } 357 }
358 358
359 _list.SetImageList(GetSysImageList(true), LVSIL_SMALL); 359 _list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
360 _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL); 360 _list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
361 361
362 unsigned columnIndex = 0; 362 unsigned columnIndex = 0;
363 _list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100); 363 _list.InsertColumn(columnIndex++, LangString(IDS_PROP_NAME), 100);
@@ -1639,15 +1639,15 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
1639 #ifndef UNDER_CE 1639 #ifndef UNDER_CE
1640 if (isDrive) 1640 if (isDrive)
1641 { 1641 {
1642 if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0) 1642 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(
1643 item.iImage = 0; 1643 fi.Name + FCHAR_PATH_SEPARATOR,
1644 FILE_ATTRIBUTE_DIRECTORY);
1644 } 1645 }
1645 else 1646 else
1646 #endif 1647 #endif
1647 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); 1648 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
1648 if (item.iImage < 0) 1649 if (item.iImage < 0)
1649 item.iImage = 0; 1650 item.iImage = 0;
1650
1651 _list.InsertItem(&item); 1651 _list.InsertItem(&item);
1652 wchar_t s[64]; 1652 wchar_t s[64];
1653 { 1653 {
@@ -1662,7 +1662,6 @@ HRESULT CBrowseDialog2::Reload(const UString &pathPrefix, const UStringVector &s
1662 ); 1662 );
1663 _list.SetSubItem(index, subItem++, s); 1663 _list.SetSubItem(index, subItem++, s);
1664 } 1664 }
1665
1666 { 1665 {
1667 s[0] = 0; 1666 s[0] = 0;
1668 Browse_ConvertSizeToString(bi, s); 1667 Browse_ConvertSizeToString(bi, s);
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
index 093534b..6ec6065 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.cpp
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -206,13 +206,15 @@ Z7_COM7F_IMF(CExtractCallbackImp::AskOverwrite(
206{ 206{
207 COverwriteDialog dialog; 207 COverwriteDialog dialog;
208 208
209 dialog.OldFileInfo.SetTime(existTime); 209 dialog.OldFileInfo.SetTime2(existTime);
210 dialog.OldFileInfo.SetSize(existSize); 210 dialog.OldFileInfo.SetSize2(existSize);
211 dialog.OldFileInfo.Name = existName; 211 dialog.OldFileInfo.Path = existName;
212 212 dialog.OldFileInfo.Is_FileSystemFile = true;
213 dialog.NewFileInfo.SetTime(newTime); 213
214 dialog.NewFileInfo.SetSize(newSize); 214 dialog.NewFileInfo.SetTime2(newTime);
215 dialog.NewFileInfo.Name = newName; 215 dialog.NewFileInfo.SetSize2(newSize);
216 dialog.NewFileInfo.Path = newName;
217 dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder;
216 218
217 ProgressDialog->WaitCreating(); 219 ProgressDialog->WaitCreating();
218 INT_PTR writeAnswer = dialog.Create(*ProgressDialog); 220 INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
index daef5ec..5c459aa 100644
--- a/CPP/7zip/UI/FileManager/ExtractCallback.h
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -224,6 +224,8 @@ public:
224 bool ProcessAltStreams; 224 bool ProcessAltStreams;
225 bool StreamMode; 225 bool StreamMode;
226 bool ThereAreMessageErrors; 226 bool ThereAreMessageErrors;
227 bool Src_Is_IO_FS_Folder;
228
227#ifndef Z7_NO_CRYPTO 229#ifndef Z7_NO_CRYPTO
228 bool PasswordIsDefined; 230 bool PasswordIsDefined;
229 bool PasswordWasAsked; 231 bool PasswordWasAsked;
@@ -286,6 +288,8 @@ public:
286 , MultiArcMode(false) 288 , MultiArcMode(false)
287 , ProcessAltStreams(true) 289 , ProcessAltStreams(true)
288 , StreamMode(false) 290 , StreamMode(false)
291 , ThereAreMessageErrors(false)
292 , Src_Is_IO_FS_Folder(false)
289#ifndef Z7_NO_CRYPTO 293#ifndef Z7_NO_CRYPTO
290 , PasswordIsDefined(false) 294 , PasswordIsDefined(false)
291 , PasswordWasAsked(false) 295 , PasswordWasAsked(false)
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
index 19d0814..70354c7 100644
--- a/CPP/7zip/UI/FileManager/FSDrives.cpp
+++ b/CPP/7zip/UI/FileManager/FSDrives.cpp
@@ -45,7 +45,8 @@ struct CPhysTempBuffer
45 ~CPhysTempBuffer() { MidFree(buffer); } 45 ~CPhysTempBuffer() { MidFree(buffer); }
46}; 46};
47 47
48static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize, 48static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath,
49 bool writeToDisk, UInt64 fileSize,
49 UInt32 bufferSize, UInt64 progressStart, IProgress *progress) 50 UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
50{ 51{
51 NIO::CInFile inFile; 52 NIO::CInFile inFile;
@@ -74,9 +75,11 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
74 75
75 for (UInt64 pos = 0; pos < fileSize;) 76 for (UInt64 pos = 0; pos < fileSize;)
76 { 77 {
77 UInt64 progressCur = progressStart + pos; 78 {
78 RINOK(progress->SetCompleted(&progressCur)) 79 const UInt64 progressCur = progressStart + pos;
79 UInt64 rem = fileSize - pos; 80 RINOK(progress->SetCompleted(&progressCur))
81 }
82 const UInt64 rem = fileSize - pos;
80 UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize); 83 UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
81 UInt32 processedSize; 84 UInt32 processedSize;
82 if (!inFile.Read(tempBuffer.buffer, curSize, processedSize)) 85 if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
@@ -91,7 +94,6 @@ static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt
91 if (curSize > bufferSize) 94 if (curSize > bufferSize)
92 return E_FAIL; 95 return E_FAIL;
93 } 96 }
94
95 if (!outFile.Write(tempBuffer.buffer, curSize, processedSize)) 97 if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
96 return GetLastError_noZero_HRESULT(); 98 return GetLastError_noZero_HRESULT();
97 if (curSize != processedSize) 99 if (curSize != processedSize)
@@ -135,9 +137,7 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
135 FOR_VECTOR (i, driveStrings) 137 FOR_VECTOR (i, driveStrings)
136 { 138 {
137 CDriveInfo di; 139 CDriveInfo di;
138
139 const FString &driveName = driveStrings[i]; 140 const FString &driveName = driveStrings[i];
140
141 di.FullSystemName = driveName; 141 di.FullSystemName = driveName;
142 if (!driveName.IsEmpty()) 142 if (!driveName.IsEmpty())
143 di.Name.SetFrom(driveName, driveName.Len() - 1); 143 di.Name.SetFrom(driveName, driveName.Len() - 1);
@@ -183,25 +183,24 @@ Z7_COM7F_IMF(CFSDrives::LoadItems())
183 { 183 {
184 FString name ("PhysicalDrive"); 184 FString name ("PhysicalDrive");
185 name.Add_UInt32(n); 185 name.Add_UInt32(n);
186
187 FString fullPath (kVolPrefix); 186 FString fullPath (kVolPrefix);
188 fullPath += name; 187 fullPath += name;
189
190 CFileInfo fi; 188 CFileInfo fi;
191 if (!fi.Find(fullPath)) 189 if (!fi.Find(fullPath))
192 continue; 190 continue;
193 191
194 CDriveInfo di; 192 CDriveInfo di;
195 di.Name = name; 193 di.Name = name;
196 di.FullSystemName = fullPath; 194 // if (_volumeMode == true) we use CDriveInfo::FullSystemName only in GetSystemIconIndex().
195 // And we need name without "\\\\.\\" prefix in GetSystemIconIndex().
196 // So we don't set di.FullSystemName = fullPath;
197 di.FullSystemName = name;
197 di.ClusterSize = 0; 198 di.ClusterSize = 0;
198 di.DriveSize = fi.Size; 199 di.DriveSize = fi.Size;
199 di.FreeSpace = 0; 200 di.FreeSpace = 0;
200 di.DriveType = 0; 201 di.DriveType = 0;
201
202 di.IsPhysicalDrive = true; 202 di.IsPhysicalDrive = true;
203 di.KnownSize = true; 203 di.KnownSize = true;
204
205 _drives.Add(di); 204 _drives.Add(di);
206 } 205 }
207 } 206 }
@@ -217,7 +216,7 @@ Z7_COM7F_IMF(CFSDrives::GetNumberOfItems(UInt32 *numItems))
217 216
218Z7_COM7F_IMF(CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)) 217Z7_COM7F_IMF(CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value))
219{ 218{
220 if (itemIndex >= (UInt32)_drives.Size()) 219 if (itemIndex >= _drives.Size())
221 return E_INVALIDARG; 220 return E_INVALIDARG;
222 NCOM::CPropVariant prop; 221 NCOM::CPropVariant prop;
223 const CDriveInfo &di = _drives[itemIndex]; 222 const CDriveInfo &di = _drives[itemIndex];
@@ -268,7 +267,7 @@ HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
268Z7_COM7F_IMF(CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)) 267Z7_COM7F_IMF(CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder))
269{ 268{
270 *resultFolder = NULL; 269 *resultFolder = NULL;
271 if (index >= (UInt32)_drives.Size()) 270 if (index >= _drives.Size())
272 return E_INVALIDARG; 271 return E_INVALIDARG;
273 const CDriveInfo &di = _drives[index]; 272 const CDriveInfo &di = _drives[index];
274 /* 273 /*
@@ -322,17 +321,14 @@ Z7_COM7F_IMF(CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value))
322 321
323Z7_COM7F_IMF(CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) 322Z7_COM7F_IMF(CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
324{ 323{
325 *iconIndex = 0; 324 *iconIndex = -1;
326 const CDriveInfo &di = _drives[index]; 325 const CDriveInfo &di = _drives[index];
327 if (di.IsPhysicalDrive) 326 return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
328 return S_OK; 327 di.FullSystemName,
329 int iconIndexTemp; 328 _volumeMode ?
330 if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0) 329 FILE_ATTRIBUTE_ARCHIVE:
331 { 330 FILE_ATTRIBUTE_DIRECTORY,
332 *iconIndex = iconIndexTemp; 331 iconIndex);
333 return S_OK;
334 }
335 return GetLastError_noZero_HRESULT();
336} 332}
337 333
338void CFSDrives::AddExt(FString &s, unsigned index) const 334void CFSDrives::AddExt(FString &s, unsigned index) const
@@ -393,10 +389,8 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
393{ 389{
394 if (numItems == 0) 390 if (numItems == 0)
395 return S_OK; 391 return S_OK;
396
397 if (moveMode) 392 if (moveMode)
398 return E_NOTIMPL; 393 return E_NOTIMPL;
399
400 if (!_volumeMode) 394 if (!_volumeMode)
401 return E_NOTIMPL; 395 return E_NOTIMPL;
402 396
@@ -411,12 +405,12 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
411 RINOK(callback->SetTotal(totalSize)) 405 RINOK(callback->SetTotal(totalSize))
412 RINOK(callback->SetNumFiles(numItems)) 406 RINOK(callback->SetNumFiles(numItems))
413 407
414 FString destPath = us2fs(path); 408 const FString destPath = us2fs(path);
415 if (destPath.IsEmpty()) 409 if (destPath.IsEmpty())
416 return E_INVALIDARG; 410 return E_INVALIDARG;
417 411
418 bool isAltDest = NName::IsAltPathPrefix(destPath); 412 const bool isAltDest = NName::IsAltPathPrefix(destPath);
419 bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back())); 413 const bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
420 414
421 if (isDirectPath) 415 if (isDirectPath)
422 { 416 {
@@ -428,7 +422,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
428 RINOK(callback->SetCompleted(&completedSize)) 422 RINOK(callback->SetCompleted(&completedSize))
429 for (i = 0; i < numItems; i++) 423 for (i = 0; i < numItems; i++)
430 { 424 {
431 unsigned index = indices[i]; 425 const unsigned index = indices[i];
432 const CDriveInfo &di = _drives[index]; 426 const CDriveInfo &di = _drives[index];
433 FString destPath2 = destPath; 427 FString destPath2 = destPath;
434 428
@@ -443,7 +437,7 @@ Z7_COM7F_IMF(CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 num
443 destPath2 += destName; 437 destPath2 += destName;
444 } 438 }
445 439
446 FString srcPath = di.GetDeviceFileIoName(); 440 const FString srcPath = di.GetDeviceFileIoName();
447 441
448 UInt64 fileSize = 0; 442 UInt64 fileSize = 0;
449 if (GetFileSize(index, fileSize) != S_OK) 443 if (GetFileSize(index, fileSize) != S_OK)
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp
index 26a2ccf..7956d86 100644
--- a/CPP/7zip/UI/FileManager/FSFolder.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolder.cpp
@@ -535,7 +535,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
535{ 535{
536 NCOM::CPropVariant prop; 536 NCOM::CPropVariant prop;
537 /* 537 /*
538 if (index >= (UInt32)Files.Size()) 538 if (index >= Files.Size())
539 { 539 {
540 CAltStream &ss = Streams[index - Files.Size()]; 540 CAltStream &ss = Streams[index - Files.Size()];
541 CDirItem &fi = Files[ss.Parent]; 541 CDirItem &fi = Files[ss.Parent];
@@ -561,7 +561,7 @@ Z7_COM7F_IMF(CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
561 case kpidComment: break; 561 case kpidComment: break;
562 default: index = ss.Parent; 562 default: index = ss.Parent;
563 } 563 }
564 if (index >= (UInt32)Files.Size()) 564 if (index >= Files.Size())
565 { 565 {
566 prop.Detach(value); 566 prop.Detach(value);
567 return S_OK; 567 return S_OK;
@@ -716,8 +716,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI
716 /* 716 /*
717 const CAltStream *ss1 = NULL; 717 const CAltStream *ss1 = NULL;
718 const CAltStream *ss2 = NULL; 718 const CAltStream *ss2 = NULL;
719 if (index1 >= (UInt32)Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; } 719 if (index1 >= Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
720 if (index2 >= (UInt32)Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; } 720 if (index2 >= Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
721 */ 721 */
722 CDirItem &fi1 = Files[index1]; 722 CDirItem &fi1 = Files[index1];
723 CDirItem &fi2 = Files[index2]; 723 CDirItem &fi2 = Files[index2];
@@ -1034,7 +1034,7 @@ Z7_COM7F_IMF(CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgr
1034 1034
1035Z7_COM7F_IMF(CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress)) 1035Z7_COM7F_IMF(CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress))
1036{ 1036{
1037 if (index >= (UInt32)Files.Size()) 1037 if (index >= Files.Size())
1038 return S_OK; 1038 return S_OK;
1039 CDirItem &fi = Files[index]; 1039 CDirItem &fi = Files[index];
1040 if (!fi.IsDir()) 1040 if (!fi.IsDir())
@@ -1080,7 +1080,7 @@ Z7_COM7F_IMF(CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress
1080 1080
1081Z7_COM7F_IMF(CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */)) 1081Z7_COM7F_IMF(CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */))
1082{ 1082{
1083 if (index >= (UInt32)Files.Size()) 1083 if (index >= Files.Size())
1084 return E_NOTIMPL; 1084 return E_NOTIMPL;
1085 const CDirItem &fi = Files[index]; 1085 const CDirItem &fi = Files[index];
1086 // FString prefix; 1086 // FString prefix;
@@ -1103,9 +1103,9 @@ Z7_COM7F_IMF(CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress
1103 UInt32 index = indices[i]; 1103 UInt32 index = indices[i];
1104 bool result = true; 1104 bool result = true;
1105 /* 1105 /*
1106 if (index >= (UInt32)Files.Size()) 1106 if (index >= Files.Size())
1107 { 1107 {
1108 const CAltStream &ss = Streams[index - (UInt32)Files.Size()]; 1108 const CAltStream &ss = Streams[index - Files.Size()];
1109 if (prevDeletedFileIndex != ss.Parent) 1109 if (prevDeletedFileIndex != ss.Parent)
1110 { 1110 {
1111 const CDirItem &fi = Files[ss.Parent]; 1111 const CDirItem &fi = Files[ss.Parent];
@@ -1134,7 +1134,7 @@ Z7_COM7F_IMF(CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress
1134Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID, 1134Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID,
1135 const PROPVARIANT *value, IProgress * /* progress */)) 1135 const PROPVARIANT *value, IProgress * /* progress */))
1136{ 1136{
1137 if (index >= (UInt32)Files.Size()) 1137 if (index >= Files.Size())
1138 return E_INVALIDARG; 1138 return E_INVALIDARG;
1139 CDirItem &fi = Files[index]; 1139 CDirItem &fi = Files[index];
1140 if (fi.Parent >= 0) 1140 if (fi.Parent >= 0)
@@ -1172,17 +1172,12 @@ Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID,
1172 1172
1173Z7_COM7F_IMF(CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) 1173Z7_COM7F_IMF(CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
1174{ 1174{
1175 if (index >= (UInt32)Files.Size()) 1175 *iconIndex = -1;
1176 if (index >= Files.Size())
1176 return E_INVALIDARG; 1177 return E_INVALIDARG;
1177 const CDirItem &fi = Files[index]; 1178 const CDirItem &fi = Files[index];
1178 *iconIndex = 0; 1179 return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
1179 int iconIndexTemp; 1180 _path + GetRelPath(fi), fi.Attrib, iconIndex);
1180 if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0)
1181 {
1182 *iconIndex = iconIndexTemp;
1183 return S_OK;
1184 }
1185 return GetLastError_noZero_HRESULT();
1186} 1181}
1187 1182
1188Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode)) 1183Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode))
diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h
index fe8538a..e2edf5f 100644
--- a/CPP/7zip/UI/FileManager/FSFolder.h
+++ b/CPP/7zip/UI/FileManager/FSFolder.h
@@ -22,11 +22,11 @@ class CFSFolder;
22 22
23struct CDirItem: public NWindows::NFile::NFind::CFileInfo 23struct CDirItem: public NWindows::NFile::NFind::CFileInfo
24{ 24{
25 #ifndef UNDER_CE 25#ifndef UNDER_CE
26 UInt64 PackSize; 26 UInt64 PackSize;
27 #endif 27#endif
28 28
29 #ifdef FS_SHOW_LINKS_INFO 29#ifdef FS_SHOW_LINKS_INFO
30 FILETIME ChangeTime; 30 FILETIME ChangeTime;
31 UInt64 FileIndex; 31 UInt64 FileIndex;
32 UInt32 NumLinks; 32 UInt32 NumLinks;
@@ -34,22 +34,21 @@ struct CDirItem: public NWindows::NFile::NFind::CFileInfo
34 bool FileInfo_WasRequested; 34 bool FileInfo_WasRequested;
35 bool ChangeTime_Defined; 35 bool ChangeTime_Defined;
36 bool ChangeTime_WasRequested; 36 bool ChangeTime_WasRequested;
37 #endif 37#endif
38 38
39 #ifndef UNDER_CE 39#ifndef UNDER_CE
40 bool PackSize_Defined; 40 bool PackSize_Defined;
41 #endif 41#endif
42 42
43 bool FolderStat_Defined; 43 bool FolderStat_Defined;
44 int Parent;
44 45
45 #ifndef UNDER_CE 46#ifndef UNDER_CE
46 CByteBuffer Reparse; 47 CByteBuffer Reparse;
47 #endif 48#endif
48 49
49 UInt64 NumFolders; 50 UInt64 NumFolders;
50 UInt64 NumFiles; 51 UInt64 NumFiles;
51
52 int Parent;
53}; 52};
54 53
55/* 54/*
@@ -126,20 +125,18 @@ class CFSFolder Z7_final:
126 Z7_IFACE_COM7_IMP(IFolderSetFlatMode) 125 Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
127 // Z7_IFACE_COM7_IMP(IFolderSetShowNtfsStreamsMode) 126 // Z7_IFACE_COM7_IMP(IFolderSetShowNtfsStreamsMode)
128 127
129private: 128 bool _flatMode;
129 bool _commentsAreLoaded;
130 // bool _scanAltStreams;
131
130 FString _path; 132 FString _path;
131
132 CObjectVector<CDirItem> Files; 133 CObjectVector<CDirItem> Files;
133 FStringVector Folders; 134 FStringVector Folders;
134 // CObjectVector<CAltStream> Streams; 135 // CObjectVector<CAltStream> Streams;
135 // CMyComPtr<IFolderFolder> _parentFolder; 136 // CMyComPtr<IFolderFolder> _parentFolder;
136 137
137 bool _commentsAreLoaded;
138 CPairsStorage _comments; 138 CPairsStorage _comments;
139 139
140 // bool _scanAltStreams;
141 bool _flatMode;
142
143 #ifdef _WIN32 140 #ifdef _WIN32
144 NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification; 141 NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
145 #endif 142 #endif
@@ -163,9 +160,11 @@ public:
163 HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); } 160 HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
164 #endif 161 #endif
165 162
166 CFSFolder() : _flatMode(false) 163 CFSFolder():
164 _flatMode(false),
165 _commentsAreLoaded(false)
167 // , _scanAltStreams(false) 166 // , _scanAltStreams(false)
168 {} 167 {}
169 168
170 void GetFullPath(const CDirItem &item, FString &path) const 169 void GetFullPath(const CDirItem &item, FString &path) const
171 { 170 {
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
index 67499fc..3582be0 100644
--- a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -515,8 +515,22 @@ static HRESULT CopyFile_Ask(
515 RINOK(state.ProgressInfo.ProgressResult) 515 RINOK(state.ProgressInfo.ProgressResult)
516 if (!res) 516 if (!res)
517 { 517 {
518 const DWORD errorCode = GetLastError();
519 UString errorMessage = NError::MyFormatMessage(Return_LastError_or_FAIL());
520 if (errorCode == ERROR_INVALID_PARAMETER)
521 {
522 NFind::CFileInfo fi;
523 if (fi.Find(srcPath) &&
524 fi.Size > (UInt32)(Int32)-1)
525 {
526 // bool isFsDetected = false;
527 // if (NSystem::Is_File_LimitedBy_4GB(destPathNew, isFsDetected) || !isFsDetected)
528 errorMessage += " File size exceeds 4 GB";
529 }
530 }
531
518 // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL. 532 // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
519 RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew)) 533 RINOK(SendMessageError(state.Callback, errorMessage, destPathNew))
520 return E_ABORT; 534 return E_ABORT;
521 } 535 }
522 state.ProgressInfo.StartPos += state.ProgressInfo.FileSize; 536 state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp
index 879f1db..e91e67f 100644
--- a/CPP/7zip/UI/FileManager/NetFolder.cpp
+++ b/CPP/7zip/UI/FileManager/NetFolder.cpp
@@ -254,28 +254,23 @@ Z7_COM7F_IMF(CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value))
254 254
255Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) 255Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex))
256{ 256{
257 if (index >= (UInt32)_items.Size()) 257 *iconIndex = -1;
258 if (index >= _items.Size())
258 return E_INVALIDARG; 259 return E_INVALIDARG;
259 *iconIndex = 0;
260 const CResourceW &resource = _items[index]; 260 const CResourceW &resource = _items[index];
261 int iconIndexTemp;
262 if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER || 261 if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
263 resource.Usage == RESOURCEUSAGE_CONNECTABLE) 262 resource.Usage == RESOURCEUSAGE_CONNECTABLE)
264 { 263 {
265 if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp)) 264 return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
266 { 265 us2fs(resource.RemoteName), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
267 *iconIndex = iconIndexTemp;
268 return S_OK;
269 }
270 } 266 }
271 else 267 else
272 { 268 {
273 if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp)) 269#if 0
274 { 270 return S_FALSE;
275 *iconIndex = iconIndexTemp; 271#else
276 return S_OK; 272 return Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
277 } 273 FTEXT("__DIR__"), FILE_ATTRIBUTE_DIRECTORY, iconIndex);
278 // *anIconIndex = GetRealIconIndex(0, L"\\\\HOME"); 274#endif
279 } 275 }
280 return GetLastError_noZero_HRESULT();
281} 276}
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
index f63277a..b15c702 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -2,8 +2,10 @@
2 2
3#include "StdAfx.h" 3#include "StdAfx.h"
4 4
5#include "../../../Common/IntToString.h"
5#include "../../../Common/StringConvert.h" 6#include "../../../Common/StringConvert.h"
6 7
8#include "../../../Windows/FileFind.h"
7#include "../../../Windows/PropVariantConv.h" 9#include "../../../Windows/PropVariantConv.h"
8#include "../../../Windows/ResourceString.h" 10#include "../../../Windows/ResourceString.h"
9 11
@@ -29,12 +31,16 @@ static const UInt32 kLangIDs[] =
29}; 31};
30#endif 32#endif
31 33
32static const unsigned kCurrentFileNameSizeLimit = 82; 34static const unsigned kCurrentFileNameSizeLimit = 72;
33static const unsigned kCurrentFileNameSizeLimit2 = 30;
34 35
35void COverwriteDialog::ReduceString(UString &s) 36void COverwriteDialog::ReduceString(UString &s)
36{ 37{
37 unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2; 38 const unsigned size =
39#ifdef UNDER_CE
40 !_isBig ? 30 : // kCurrentFileNameSizeLimit2
41#endif
42 kCurrentFileNameSizeLimit;
43
38 if (s.Len() > size) 44 if (s.Len() > size)
39 { 45 {
40 s.Delete(size / 2, s.Len() - size); 46 s.Delete(size / 2, s.Len() - size);
@@ -42,66 +48,201 @@ void COverwriteDialog::ReduceString(UString &s)
42 } 48 }
43 if (!s.IsEmpty() && s.Back() == ' ') 49 if (!s.IsEmpty() && s.Back() == ' ')
44 { 50 {
45 // s += (wchar_t)(0x2423); 51 // s += (wchar_t)(0x2423); // visible space
46 s.InsertAtFront(L'\"'); 52 s.InsertAtFront(L'\"');
47 s += L'\"'; 53 s.Add_Char('\"');
48 } 54 }
49} 55}
50 56
51void COverwriteDialog::SetFileInfoControl(unsigned textID, unsigned iconID, 57
52 const NOverwriteDialog::CFileInfo &fileInfo) 58void COverwriteDialog::SetItemIcon(unsigned iconID, HICON hIcon)
59{
60 NControl::CStatic staticContol;
61 staticContol.Attach(GetItem(iconID));
62 hIcon = staticContol.SetIcon(hIcon);
63 if (hIcon)
64 DestroyIcon(hIcon);
65}
66
67void AddSizeValue(UString &s, UInt64 value);
68void AddSizeValue(UString &s, UInt64 value)
53{ 69{
54 UString sizeString;
55 if (fileInfo.SizeIsDefined)
56 sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
57
58 const UString &fileName = fileInfo.Name;
59 int slashPos = fileName.ReverseFind_PathSepar();
60 UString s1 = fileName.Left((unsigned)(slashPos + 1));
61 UString s2 = fileName.Ptr((unsigned)(slashPos + 1));
62
63 ReduceString(s1);
64 ReduceString(s2);
65
66 UString s = s1;
67 s.Add_LF();
68 s += s2;
69 s.Add_LF();
70 s += sizeString;
71 s.Add_LF();
72
73 if (fileInfo.TimeIsDefined)
74 { 70 {
75 AddLangString(s, IDS_PROP_MTIME); 71 wchar_t sz[32];
76 s += ": "; 72 ConvertUInt64ToString(value, sz);
77 char t[64]; 73 s += MyFormatNew(IDS_FILE_SIZE, sz);
78 ConvertUtcFileTimeToString(fileInfo.Time, t);
79 s += t;
80 } 74 }
75 if (value >= (1 << 10))
76 {
77 char c;
78 if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }
79 else if (value >= (10 << 20)) { value >>= 20; c = 'M'; }
80 else { value >>= 10; c = 'K'; }
81 s += " : ";
82 s.Add_UInt64(value);
83 s.Add_Space();
84 s.Add_Char(c);
85 s += "iB";
86 }
87}
81 88
82 NControl::CDialogChildControl control;
83 control.Init(*this, textID);
84 control.SetText(s);
85 89
86 SHFILEINFO shellFileInfo; 90void COverwriteDialog::SetFileInfoControl(
87 if (::SHGetFileInfo( 91 const NOverwriteDialog::CFileInfo &fileInfo,
88 GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo, 92 unsigned textID,
89 sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON)) 93 unsigned iconID,
94 unsigned iconID_2)
95{
96 {
97 const UString &path = fileInfo.Path;
98 const int slashPos = path.ReverseFind_PathSepar();
99 UString s = path.Left((unsigned)(slashPos + 1));
100 ReduceString(s);
101 s.Add_LF();
102 {
103 UString s2 = path.Ptr((unsigned)(slashPos + 1));
104 ReduceString(s2);
105 s += s2;
106 }
107 s.Add_LF();
108 if (fileInfo.Size_IsDefined)
109 AddSizeValue(s, fileInfo.Size);
110 s.Add_LF();
111 if (fileInfo.Time_IsDefined)
112 {
113 AddLangString(s, IDS_PROP_MTIME);
114 s += ": ";
115 char t[64];
116 ConvertUtcFileTimeToString(fileInfo.Time, t);
117 s += t;
118 }
119 SetItemText(textID, s);
120 }
121/*
122 SHGetFileInfo():
123 DOCs: If uFlags does not contain SHGFI_EXETYPE or SHGFI_SYSICONINDEX,
124 the return value is nonzero if successful, or zero otherwise.
125 We don't use SHGFI_EXETYPE or SHGFI_SYSICONINDEX here.
126 win10: we call with SHGFI_ICON flag set.
127 it returns 0: if error : (shFileInfo::*) members are not set.
128 it returns non_0, if successful, and retrieve:
129 { shFileInfo.hIcon != NULL : the handle to icon (must be destroyed by our code)
130 shFileInfo.iIcon is index of the icon image within the system image list.
131 }
132 Note:
133 If we send path to ".exe" file,
134 SHGFI_USEFILEATTRIBUTES flag is ignored, and it tries to open file.
135 and return icon from that exe file.
136 So we still need to reduce path, if want to get raw icon of exe file.
137
138 if (name.Len() >= MAX_PATH))
139 {
140 it can return:
141 return 0.
142 return 1 and:
143 { shFileInfo.hIcon != NULL : is some default icon for file
144 shFileInfo.iIcon == 0
145 }
146 return results (0 or 1) can depend from:
147 - unicode/non-unicode
148 - (SHGFI_USEFILEATTRIBUTES) flag
149 - exact file extension (.exe).
150 }
151*/
152 int iconIndex = -1;
153 for (unsigned i = 0; i < 2; i++)
90 { 154 {
91 NControl::CStatic staticContol; 155 CSysString name = GetSystemString(fileInfo.Path);
92 staticContol.Attach(GetItem(iconID)); 156 if (i != 0)
93 staticContol.SetIcon(shellFileInfo.hIcon); 157 {
158 if (!fileInfo.Is_FileSystemFile)
159 break;
160 if (name.Len() < 4 ||
161 (!StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".exe") &&
162 !StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".ico")))
163 break;
164 // if path for ".exe" file is long, it returns default icon (shFileInfo.iIcon == 0).
165 // We don't want to show that default icon.
166 // But we will check for default icon later instead of MAX_PATH check here.
167 // if (name.Len() >= MAX_PATH) break; // optional
168 }
169 else
170 {
171 // we need only file extension with dot
172 const int separ = name.ReverseFind_PathSepar();
173 name.DeleteFrontal((unsigned)(separ + 1));
174 // if (name.Len() >= MAX_PATH)
175 {
176 const int dot = name.ReverseFind_Dot();
177 if (dot >= 0)
178 name.DeleteFrontal((unsigned)dot);
179 // else name.Empty(); to set default name below
180 }
181 // name.Empty(); // for debug
182 }
183
184 if (name.IsEmpty())
185 {
186 // If we send empty name, SHGetFileInfo() returns some strange icon.
187 // So we use common dummy name without extension,
188 // and SHGetFileInfo() will return default icon (iIcon == 0)
189 name = "__file__";
190 }
191
192 DWORD attrib = FILE_ATTRIBUTE_ARCHIVE;
193 if (fileInfo.Is_FileSystemFile)
194 {
195 NFile::NFind::CFileInfo fi;
196 if (fi.Find(us2fs(fileInfo.Path)) && !fi.IsAltStream && !fi.IsDir())
197 attrib = fi.Attrib;
198 }
199
200 SHFILEINFO shFileInfo;
201 // ZeroMemory(&shFileInfo, sizeof(shFileInfo)); // optional
202 shFileInfo.hIcon = NULL; // optional
203 shFileInfo.iIcon = -1; // optional
204 // memset(&shFileInfo, 1, sizeof(shFileInfo)); // for debug
205 const DWORD_PTR res = ::SHGetFileInfo(name, attrib,
206 &shFileInfo, sizeof(shFileInfo),
207 SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SHELLICONSIZE |
208 // (i == 0 ? SHGFI_USEFILEATTRIBUTES : 0)
209 SHGFI_USEFILEATTRIBUTES
210 // we use SHGFI_USEFILEATTRIBUTES for second icon, because
211 // it still returns real icon from exe files
212 );
213 if (res && shFileInfo.hIcon)
214 {
215 // we don't show second icon, if icon index (iIcon) is same
216 // as first icon index of first shown icon (exe file without icon)
217 if ( shFileInfo.iIcon >= 0
218 && shFileInfo.iIcon != iconIndex
219 && (shFileInfo.iIcon != 0 || i == 0)) // we don't want default icon for second icon
220 {
221 iconIndex = shFileInfo.iIcon;
222 SetItemIcon(i == 0 ? iconID : iconID_2, shFileInfo.hIcon);
223 }
224 else
225 DestroyIcon(shFileInfo.hIcon);
226 }
94 } 227 }
95} 228}
96 229
230
231
97bool COverwriteDialog::OnInit() 232bool COverwriteDialog::OnInit()
98{ 233{
99 #ifdef Z7_LANG 234 #ifdef Z7_LANG
100 LangSetWindowText(*this, IDD_OVERWRITE); 235 LangSetWindowText(*this, IDD_OVERWRITE);
101 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs)); 236 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
102 #endif 237 #endif
103 SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo); 238 SetFileInfoControl(OldFileInfo,
104 SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo); 239 IDT_OVERWRITE_OLD_FILE_SIZE_TIME,
240 IDI_OVERWRITE_OLD_FILE,
241 IDI_OVERWRITE_OLD_FILE_2);
242 SetFileInfoControl(NewFileInfo,
243 IDT_OVERWRITE_NEW_FILE_SIZE_TIME,
244 IDI_OVERWRITE_NEW_FILE,
245 IDI_OVERWRITE_NEW_FILE_2);
105 NormalizePosition(); 246 NormalizePosition();
106 247
107 if (!ShowExtraButtons) 248 if (!ShowExtraButtons)
@@ -122,6 +263,15 @@ bool COverwriteDialog::OnInit()
122 return CModalDialog::OnInit(); 263 return CModalDialog::OnInit();
123} 264}
124 265
266bool COverwriteDialog::OnDestroy()
267{
268 SetItemIcon(IDI_OVERWRITE_OLD_FILE, NULL);
269 SetItemIcon(IDI_OVERWRITE_OLD_FILE_2, NULL);
270 SetItemIcon(IDI_OVERWRITE_NEW_FILE, NULL);
271 SetItemIcon(IDI_OVERWRITE_NEW_FILE_2, NULL);
272 return false; // we return (false) to perform default dialog operation
273}
274
125bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) 275bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
126{ 276{
127 switch (buttonID) 277 switch (buttonID)
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h
index a9ca991..9f0801d 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.h
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h
@@ -12,68 +12,78 @@ namespace NOverwriteDialog
12{ 12{
13 struct CFileInfo 13 struct CFileInfo
14 { 14 {
15 bool SizeIsDefined; 15 bool Size_IsDefined;
16 bool TimeIsDefined; 16 bool Time_IsDefined;
17 bool Is_FileSystemFile;
17 UInt64 Size; 18 UInt64 Size;
18 FILETIME Time; 19 FILETIME Time;
19 UString Name; 20 UString Path;
21
22 void SetTime(const FILETIME &t)
23 {
24 Time = t;
25 Time_IsDefined = true;
26 }
20 27
21 void SetTime(const FILETIME *t) 28 void SetTime2(const FILETIME *t)
22 { 29 {
23 if (!t) 30 if (!t)
24 TimeIsDefined = false; 31 Time_IsDefined = false;
25 else 32 else
26 { 33 SetTime(*t);
27 TimeIsDefined = true;
28 Time = *t;
29 }
30 } 34 }
31 35
32 void SetSize(UInt64 size) 36 void SetSize(UInt64 size)
33 { 37 {
34 SizeIsDefined = true;
35 Size = size; 38 Size = size;
39 Size_IsDefined = true;
36 } 40 }
37 41
38 void SetSize(const UInt64 *size) 42 void SetSize2(const UInt64 *size)
39 { 43 {
40 if (!size) 44 if (!size)
41 SizeIsDefined = false; 45 Size_IsDefined = false;
42 else 46 else
43 SetSize(*size); 47 SetSize(*size);
44 } 48 }
49
50 CFileInfo():
51 Size_IsDefined(false),
52 Time_IsDefined(false),
53 Is_FileSystemFile(false)
54 {}
45 }; 55 };
46} 56}
47 57
48class COverwriteDialog: public NWindows::NControl::CModalDialog 58class COverwriteDialog: public NWindows::NControl::CModalDialog
49{ 59{
60#ifdef UNDER_CE
50 bool _isBig; 61 bool _isBig;
62#endif
51 63
52 void SetFileInfoControl(unsigned textID, unsigned iconID, const NOverwriteDialog::CFileInfo &fileInfo); 64 void SetItemIcon(unsigned iconID, HICON hIcon);
65 void SetFileInfoControl(const NOverwriteDialog::CFileInfo &fileInfo, unsigned textID, unsigned iconID, unsigned iconID_2);
53 virtual bool OnInit() Z7_override; 66 virtual bool OnInit() Z7_override;
67 virtual bool OnDestroy() Z7_override;
54 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; 68 virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;
55 void ReduceString(UString &s); 69 void ReduceString(UString &s);
56 70
57public: 71public:
58 bool ShowExtraButtons; 72 bool ShowExtraButtons;
59 bool DefaultButton_is_NO; 73 bool DefaultButton_is_NO;
60 74 NOverwriteDialog::CFileInfo OldFileInfo;
75 NOverwriteDialog::CFileInfo NewFileInfo;
61 76
62 COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {} 77 COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}
63 78
64 INT_PTR Create(HWND parent = NULL) 79 INT_PTR Create(HWND parent = NULL)
65 { 80 {
81#ifdef UNDER_CE
66 BIG_DIALOG_SIZE(280, 200); 82 BIG_DIALOG_SIZE(280, 200);
67 #ifdef UNDER_CE
68 _isBig = isBig; 83 _isBig = isBig;
69 #else 84#endif
70 _isBig = true;
71 #endif
72 return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent); 85 return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
73 } 86 }
74
75 NOverwriteDialog::CFileInfo OldFileInfo;
76 NOverwriteDialog::CFileInfo NewFileInfo;
77}; 87};
78 88
79#endif 89#endif
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
index 29f9912..112d5d8 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialog.rc
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
@@ -1,7 +1,7 @@
1#include "OverwriteDialogRes.h" 1#include "OverwriteDialogRes.h"
2#include "../../GuiCommon.rc" 2#include "../../GuiCommon.rc"
3 3
4#define xc 280 4#define xc 340
5#define yc 200 5#define yc 200
6 6
7#undef iconSize 7#undef iconSize
@@ -25,11 +25,13 @@ BEGIN
25 LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8 25 LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8
26 26
27 ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize 27 ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize
28 ICON "", IDI_OVERWRITE_OLD_FILE_2, m, 44 + iconSize, iconSize, iconSize
28 LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX 29 LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX
29 30
30 LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8 31 LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8
31 32
32 ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize 33 ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize
34 ICON "", IDI_OVERWRITE_NEW_FILE_2, m, 114 + iconSize, iconSize, iconSize
33 LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX 35 LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX
34 36
35 PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys 37 PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
index b480ba1..24beb33 100644
--- a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
+++ b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
@@ -11,7 +11,9 @@
11#define IDB_NO_TO_ALL 441 11#define IDB_NO_TO_ALL 441
12 12
13#define IDI_OVERWRITE_OLD_FILE 100 13#define IDI_OVERWRITE_OLD_FILE 100
14#define IDI_OVERWRITE_NEW_FILE 101 14#define IDI_OVERWRITE_OLD_FILE_2 101
15
16#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102 15#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102
17#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103 16
17#define IDI_OVERWRITE_NEW_FILE 110
18#define IDI_OVERWRITE_NEW_FILE_2 111
19#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 112
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
index cdb5ba4..f3fb38e 100644
--- a/CPP/7zip/UI/FileManager/Panel.cpp
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -420,8 +420,8 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
420 _listView._panel = this; 420 _listView._panel = this;
421 _listView.SetWindowProc(); 421 _listView.SetWindowProc();
422 422
423 _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL); 423 _listView.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);
424 _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL); 424 _listView.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);
425 425
426 // _exStyle |= LVS_EX_HEADERDRAGDROP; 426 // _exStyle |= LVS_EX_HEADERDRAGDROP;
427 // DWORD extendedStyle = _listView.GetExtendedListViewStyle(); 427 // DWORD extendedStyle = _listView.GetExtendedListViewStyle();
@@ -506,17 +506,15 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
506 #endif 506 #endif
507 , NULL, 507 , NULL,
508 WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL, 508 WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
509 0, 0, 100, 520, 509 0, 0, 100, 620,
510 (_headerReBar ? _headerToolBar : (HWND)*this), 510 (_headerReBar ? _headerToolBar : (HWND)*this),
511 (HMENU)(UINT_PTR)(_comboBoxID), 511 (HMENU)(UINT_PTR)(_comboBoxID),
512 g_hInstance, NULL); 512 g_hInstance, NULL);
513 #ifndef UNDER_CE
514 _headerComboBox.SetUnicodeFormat(true);
515
516 _headerComboBox.SetImageList(GetSysImageList(true));
517 513
514#ifndef UNDER_CE
515 _headerComboBox.SetUnicodeFormat(true);
516 _headerComboBox.SetImageList(Shell_Get_SysImageList_smallIcons(true));
518 _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC); 517 _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
519
520 /* 518 /*
521 _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox)); 519 _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
522 _headerComboBox._panel = this; 520 _headerComboBox._panel = this;
@@ -525,9 +523,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
525 LONG_PTR(ComboBoxSubclassProc)); 523 LONG_PTR(ComboBoxSubclassProc));
526 */ 524 */
527 _comboBoxEdit.Attach(_headerComboBox.GetEditControl()); 525 _comboBoxEdit.Attach(_headerComboBox.GetEditControl());
528
529 // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0); 526 // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
530
531 _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit)); 527 _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
532 _comboBoxEdit._panel = this; 528 _comboBoxEdit._panel = this;
533 #ifndef _UNICODE 529 #ifndef _UNICODE
@@ -538,8 +534,7 @@ bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
538 #endif 534 #endif
539 _comboBoxEdit._origWindowProc = 535 _comboBoxEdit._origWindowProc =
540 (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc)); 536 (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
541 537#endif
542 #endif
543 538
544 if (_headerReBar) 539 if (_headerReBar)
545 { 540 {
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
index 5cbc35d..1b708f7 100644
--- a/CPP/7zip/UI/FileManager/Panel.h
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -147,11 +147,11 @@ public:
147struct CTempFileInfo 147struct CTempFileInfo
148{ 148{
149 UInt32 FileIndex; // index of file in folder 149 UInt32 FileIndex; // index of file in folder
150 bool NeedDelete;
150 UString RelPath; // Relative path of file from Folder 151 UString RelPath; // Relative path of file from Folder
151 FString FolderPath; 152 FString FolderPath;
152 FString FilePath; 153 FString FilePath;
153 NWindows::NFile::NFind::CFileInfo FileInfo; 154 NWindows::NFile::NFind::CFileInfo FileInfo;
154 bool NeedDelete;
155 155
156 CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {} 156 CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {}
157 void DeleteDirAndFile() const 157 void DeleteDirAndFile() const
@@ -171,15 +171,15 @@ struct CTempFileInfo
171 171
172struct CFolderLink: public CTempFileInfo 172struct CFolderLink: public CTempFileInfo
173{ 173{
174 bool IsVirtual;
175 bool UsePassword;
174 NWindows::NDLL::CLibrary Library; 176 NWindows::NDLL::CLibrary Library;
175 CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0]) 177 CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
176 UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level) 178 UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
177 bool UsePassword;
178 UString Password; 179 UString Password;
179 bool IsVirtual;
180 180
181 UString VirtualPath; // without tail slash 181 UString VirtualPath; // without tail slash
182 CFolderLink(): UsePassword(false), IsVirtual(false) {} 182 CFolderLink(): IsVirtual(false), UsePassword(false) {}
183 183
184 bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const 184 bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
185 { 185 {
@@ -310,7 +310,7 @@ struct COpenResult
310 310
311class CPanel Z7_final: public NWindows::NControl::CWindow2 311class CPanel Z7_final: public NWindows::NControl::CWindow2
312{ 312{
313 CExtToIconMap _extToIconMap; 313 // CExtToIconMap _extToIconMap;
314 UINT _baseID; 314 UINT _baseID;
315 unsigned _comboBoxID; 315 unsigned _comboBoxID;
316 UINT _statusBarID; 316 UINT _statusBarID;
@@ -324,7 +324,7 @@ class CPanel Z7_final: public NWindows::NControl::CWindow2
324 virtual void OnDestroy() Z7_override; 324 virtual void OnDestroy() Z7_override;
325 virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result) Z7_override; 325 virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result) Z7_override;
326 326
327 void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList); 327 void AddComboBoxItem(const UString &name, int iconIndex, unsigned indent, bool addToList);
328 328
329 bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result); 329 bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);
330 330
@@ -355,7 +355,7 @@ public:
355 HWND _mainWindow; 355 HWND _mainWindow;
356 CPanelCallback *_panelCallback; 356 CPanelCallback *_panelCallback;
357 357
358 void SysIconsWereChanged() { _extToIconMap.Clear(); } 358 // void SysIconsWereChanged() { _extToIconMap.Clear(); }
359 359
360 void DeleteItems(bool toRecycleBin); 360 void DeleteItems(bool toRecycleBin);
361 void CreateFolder(); 361 void CreateFolder();
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
index 40a347f..36a0f6d 100644
--- a/CPP/7zip/UI/FileManager/PanelCopy.cpp
+++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp
@@ -189,7 +189,9 @@ HRESULT CPanel::CopyTo(CCopyToOptions &options,
189 189
190 extracter.ExtractCallbackSpec = new CExtractCallbackImp; 190 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
191 extracter.ExtractCallback = extracter.ExtractCallbackSpec; 191 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
192 192 extracter.ExtractCallbackSpec->Src_Is_IO_FS_Folder =
193 IsFSFolder() || IsAltStreamsFolder();
194 // options.src_Is_IO_FS_Folder;
193 extracter.options = &options; 195 extracter.options = &options;
194 extracter.ExtractCallbackSpec->ProgressDialog = &extracter; 196 extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
195 extracter.CompressingMode = false; 197 extracter.CompressingMode = false;
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
index 406e304..c34cb74 100644
--- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -368,14 +368,41 @@ void CPanel::LoadFullPath()
368 _currentFolderPrefix += GetFolderPath(_folder); 368 _currentFolderPrefix += GetFolderPath(_folder);
369} 369}
370 370
371static int GetRealIconIndex(CFSTR path, DWORD attributes) 371
372
373static int GetRealIconIndex_for_DirPath(CFSTR path, DWORD attrib)
372{ 374{
375 attrib |= FILE_ATTRIBUTE_DIRECTORY; // optional
373 int index = -1; 376 int index = -1;
374 if (GetRealIconIndex(path, attributes, index) != 0) 377 if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(path, attrib, index))
375 return index; 378 if (index >= 0)
376 return -1; 379 return index;
380 return g_Ext_to_Icon_Map.GetIconIndex_DIR(attrib);
381}
382
383
384extern UString RootFolder_GetName_Computer(int &iconIndex);
385extern UString RootFolder_GetName_Network(int &iconIndex);
386extern UString RootFolder_GetName_Documents(int &iconIndex);
387
388
389static int Find_FileExtension_DotPos_in_path(const wchar_t *path)
390{
391 int dotPos = -1;
392 unsigned i;
393 for (i = 0;; i++)
394 {
395 const wchar_t c = path[i];
396 if (c == 0)
397 return dotPos;
398 if (c == '.')
399 dotPos = (int)i;
400 else if (IS_PATH_SEPAR(c) || c == ':')
401 dotPos = -1;
402 }
377} 403}
378 404
405
379void CPanel::LoadFullPathAndShow() 406void CPanel::LoadFullPathAndShow()
380{ 407{
381 LoadFullPath(); 408 LoadFullPath();
@@ -387,30 +414,97 @@ void CPanel::LoadFullPathAndShow()
387 414
388 COMBOBOXEXITEM item; 415 COMBOBOXEXITEM item;
389 item.mask = 0; 416 item.mask = 0;
417 item.iImage = -1;
390 418
391 UString path = _currentFolderPrefix; 419 UString path = _currentFolderPrefix;
392 if (path.Len() > 420 // path = "\\\\.\\PhysicalDrive1\\"; // for debug
393 #ifdef _WIN32 421 // path = "\\\\.\\y:\\"; // for debug
394 3 422 if (!path.IsEmpty())
395 #else
396 1
397 #endif
398 && IS_PATH_SEPAR(path.Back()))
399 path.DeleteBack();
400
401 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
402
403 // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path
404 if (path.IsPrefixedBy(L"\\\\.\\"))
405 path = "_TestFolder_";
406 else
407 { 423 {
408 CFileInfo fi; 424 const unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
409 if (fi.Find(us2fs(path))) 425 if (rootPrefixSize == 0 && path[0] != '\\')
410 attrib = fi.Attrib; 426 {
427 int iconIndex = -1;
428 UString name_Computer = RootFolder_GetName_Computer(iconIndex);
429 name_Computer.Add_PathSepar();
430 if (path == name_Computer
431 || path == L"\\\\?\\")
432 item.iImage = iconIndex;
433 else
434 {
435 UString name = RootFolder_GetName_Network(iconIndex);
436 name.Add_PathSepar();
437 if (path == name)
438 item.iImage = iconIndex;
439 }
440 }
441
442 if (item.iImage < 0)
443 {
444 if (rootPrefixSize == 0 || rootPrefixSize == path.Len())
445 {
446 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
447 CFileInfo info;
448 if (info.Find(us2fs(path)))
449 attrib = info.Attrib;
450 NName::If_IsSuperPath_RemoveSuperPrefix(path);
451 item.iImage = GetRealIconIndex_for_DirPath(us2fs(path), attrib);
452 }
453 else if (rootPrefixSize == NName::kDevicePathPrefixSize
454 && NName::IsDevicePath(us2fs(path.Left(path.Len() - 1))))
455 {
456 if (path.IsPrefixedBy_Ascii_NoCase("\\\\.\\"))
457 path.DeleteFrontal(4);
458 if (path.Len() > 3) // is not "c:\\"
459 {
460 // PhysicalDrive
461 if (path.Back() == '\\')
462 path.DeleteBack();
463 }
464 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), FILE_ATTRIBUTE_ARCHIVE);
465 }
466 else
467 {
468 if (path.Back() == '\\')
469 path.DeleteBack();
470 bool need_Fs_Check = true;
471 bool is_File = false;
472 if (!_parentFolders.IsEmpty())
473 {
474 const CFolderLink &link = _parentFolders.Back();
475 if (link.VirtualPath == path)
476 {
477 is_File = true;
478 if (_parentFolders.Size() != 1)
479 need_Fs_Check = false;
480 }
481 else
482 need_Fs_Check = false;
483 }
484 if (need_Fs_Check)
485 {
486 CFileInfo info;
487 const bool finded = info.Find(us2fs(path));
488 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
489 if (finded)
490 attrib = info.Attrib;
491 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), attrib);
492 }
493 if (item.iImage <= 0 && is_File)
494 {
495 int dotPos = Find_FileExtension_DotPos_in_path(path);
496 if (dotPos < 0)
497 dotPos = (int)path.Len();
498 item.iImage = g_Ext_to_Icon_Map.GetIconIndex(FILE_ATTRIBUTE_ARCHIVE, path.Ptr(dotPos));
499 }
500 }
501 }
411 } 502 }
412 item.iImage = GetRealIconIndex(us2fs(path), attrib);
413 503
504 if (item.iImage < 0)
505 item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
506 // if (item.iImage < 0) item.iImage = 0;
507 // item.iImage = -1; // for debug
414 if (item.iImage >= 0) 508 if (item.iImage >= 0)
415 { 509 {
416 item.iSelectedImage = item.iImage; 510 item.iSelectedImage = item.iImage;
@@ -495,13 +589,13 @@ bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
495} 589}
496#endif 590#endif
497 591
498void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList) 592void CPanel::AddComboBoxItem(const UString &name, int iconIndex, unsigned indent, bool addToList)
499{ 593{
500 #ifdef UNDER_CE 594 #ifdef UNDER_CE
501 595
502 UString s; 596 UString s;
503 iconIndex = iconIndex; 597 iconIndex = iconIndex;
504 for (int i = 0; i < indent; i++) 598 for (unsigned i = 0; i < indent; i++)
505 s += " "; 599 s += " ";
506 _headerComboBox.AddString(s + name); 600 _headerComboBox.AddString(s + name);
507 601
@@ -509,23 +603,26 @@ void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, boo
509 603
510 COMBOBOXEXITEMW item; 604 COMBOBOXEXITEMW item;
511 item.mask = CBEIF_TEXT | CBEIF_INDENT; 605 item.mask = CBEIF_TEXT | CBEIF_INDENT;
606 if (iconIndex < 0)
607 iconIndex = g_Ext_to_Icon_Map.GetIconIndex_DIR();
512 item.iSelectedImage = item.iImage = iconIndex; 608 item.iSelectedImage = item.iImage = iconIndex;
513 if (iconIndex >= 0) 609 if (iconIndex >= 0)
514 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE); 610 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
515 item.iItem = -1; 611 item.iItem = -1;
516 item.iIndent = indent; 612 item.iIndent = (int)indent;
517 item.pszText = name.Ptr_non_const(); 613 item.pszText = name.Ptr_non_const();
518 _headerComboBox.InsertItem(&item); 614 _headerComboBox.InsertItem(&item);
519 615
520 #endif 616 #endif
521 617
522 if (addToList) 618 if (addToList)
523 ComboBoxPaths.Add(name); 619 {
620 UString s = name;
621 s.Add_PathSepar();
622 ComboBoxPaths.Add(s);
623 }
524} 624}
525 625
526extern UString RootFolder_GetName_Computer(int &iconIndex);
527extern UString RootFolder_GetName_Network(int &iconIndex);
528extern UString RootFolder_GetName_Documents(int &iconIndex);
529 626
530bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) 627bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
531{ 628{
@@ -537,56 +634,168 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
537 ComboBoxPaths.Clear(); 634 ComboBoxPaths.Clear();
538 _headerComboBox.ResetContent(); 635 _headerComboBox.ResetContent();
539 636
540 unsigned i; 637 UString sumPath;
541 UStringVector pathParts; 638 UStringVector pathParts;
542 639 unsigned indent = 0;
543 SplitPathToParts(_currentFolderPrefix, pathParts);
544 UString sumPass;
545 if (!pathParts.IsEmpty())
546 pathParts.DeleteBack();
547 for (i = 0; i < pathParts.Size(); i++)
548 { 640 {
549 const UString name = pathParts[i]; 641 UString path = _currentFolderPrefix;
550 sumPass += name; 642 // path = L"\\\\.\\y:\\"; // for debug
551 sumPass.Add_PathSepar(); 643 UString prefix0;
552 CFileInfo info; 644 if (path.IsPrefixedBy_Ascii_NoCase("\\\\"))
553 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; 645 {
554 if (info.Find(us2fs(sumPass))) 646 const int separ = FindCharPosInString(path.Ptr(2), '\\');
555 attrib = info.Attrib; 647 if (separ > 0
556 AddComboBoxItem( 648 && (separ > 1 || path[2] != '.')) // "\\\\.\\" will be processed later
557 name.IsEmpty() ? L"\\" : name, 649 {
558 GetRealIconIndex(us2fs(sumPass), attrib), 650 const UString s = path.Left(2 + separ);
559 (int)i, // iIndent 651 prefix0 = s;
560 false); // addToList 652 prefix0.Add_PathSepar();
561 ComboBoxPaths.Add(sumPass); 653 AddComboBoxItem(s,
654 GetRealIconIndex_for_DirPath(us2fs(prefix0), FILE_ATTRIBUTE_DIRECTORY),
655 indent++,
656 false); // addToList
657 ComboBoxPaths.Add(prefix0);
658 }
659 }
660
661 unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
662
663 sumPath = path;
664
665 if (rootPrefixSize <= prefix0.Len())
666 {
667 rootPrefixSize = prefix0.Len();
668 sumPath.DeleteFrom(rootPrefixSize);
669 }
670 else
671 {
672 // rootPrefixSize > prefix0.Len()
673 sumPath.DeleteFrom(rootPrefixSize);
674
675 CFileInfo info;
676 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
677 if (info.Find(us2fs(sumPath)) && info.IsDir())
678 attrib = info.Attrib;
679 UString s = sumPath.Ptr(prefix0.Len());
680 if (!s.IsEmpty())
681 {
682 const wchar_t c = s.Back();
683 if (IS_PATH_SEPAR(c))
684 s.DeleteBack();
685 }
686 UString path_for_icon = sumPath;
687 NName::If_IsSuperPath_RemoveSuperPrefix(path_for_icon);
688
689 AddComboBoxItem(s,
690 GetRealIconIndex_for_DirPath(us2fs(path_for_icon), attrib),
691 indent++,
692 false); // addToList
693 ComboBoxPaths.Add(sumPath);
694 }
695
696 path.DeleteFrontal(rootPrefixSize);
697 SplitPathToParts(path, pathParts);
562 } 698 }
563 699
564 #ifndef UNDER_CE 700 // it's expected that pathParts.Back() is empty, because _currentFolderPrefix has PathSeparator.
701 unsigned next_Arc_index = 0;
702 int iconIndex_Computer;
703 const UString name_Computer = RootFolder_GetName_Computer(iconIndex_Computer);
565 704
566 int iconIndex; 705 // const bool is_devicePrefix = (sumPath == L"\\\\.\\");
567 UString name;
568 name = RootFolder_GetName_Documents(iconIndex);
569 AddComboBoxItem(name, iconIndex, 0, true);
570 706
571 name = RootFolder_GetName_Computer(iconIndex); 707 if (pathParts.Size() > 1)
572 AddComboBoxItem(name, iconIndex, 0, true); 708 if (!sumPath.IsEmpty()
573 709 || pathParts.Size() != 2
574 FStringVector driveStrings; 710 || pathParts[0] != name_Computer)
575 MyGetLogicalDriveStrings(driveStrings); 711 for (unsigned i = 0; i + 1 < pathParts.Size(); i++)
576 for (i = 0; i < driveStrings.Size(); i++)
577 { 712 {
578 FString s = driveStrings[i]; 713 UString name = pathParts[i];
579 ComboBoxPaths.Add(fs2us(s)); 714 sumPath += name;
580 int iconIndex2 = GetRealIconIndex(s, 0); 715
581 if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR) 716 bool isRootDir_inLink = false;
582 s.DeleteBack(); 717 if (next_Arc_index < _parentFolders.Size())
583 AddComboBoxItem(fs2us(s), iconIndex2, 1, false); 718 {
719 const CFolderLink &link = _parentFolders[next_Arc_index];
720 if (link.VirtualPath == sumPath)
721 {
722 isRootDir_inLink = true;
723 next_Arc_index++;
724 }
725 }
726
727 int iconIndex = -1;
728 DWORD attrib = isRootDir_inLink ?
729 FILE_ATTRIBUTE_ARCHIVE:
730 FILE_ATTRIBUTE_DIRECTORY;
731 if (next_Arc_index == 0
732 || (next_Arc_index == 1 && isRootDir_inLink))
733 {
734 if (i == 0 && NName::IsDevicePath(us2fs(sumPath)))
735 {
736 UString path = name;
737 path.Add_PathSepar();
738 attrib = FILE_ATTRIBUTE_ARCHIVE;
739 // FILE_ATTRIBUTE_DIRECTORY;
740 }
741 else
742 {
743 CFileInfo info;
744 if (info.Find(us2fs(sumPath)))
745 attrib = info.Attrib;
746 }
747 iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(sumPath), attrib);
748 }
749
750 if (iconIndex < 0)
751 iconIndex = g_Ext_to_Icon_Map.GetIconIndex(attrib, name);
752 // iconIndex = -1; // for debug
753 if (iconIndex < 0 && isRootDir_inLink)
754 iconIndex = 0; // default file
755
756 sumPath.Add_PathSepar();
757
758 ComboBoxPaths.Add(sumPath);
759 if (name.IsEmpty())
760 name.Add_PathSepar();
761 AddComboBoxItem(name, iconIndex, indent++,
762 false); // addToList
584 } 763 }
585 764
586 name = RootFolder_GetName_Network(iconIndex); 765#ifndef UNDER_CE
587 AddComboBoxItem(name, iconIndex, 0, true);
588 766
589 #endif 767 {
768 int iconIndex;
769 const UString name = RootFolder_GetName_Documents(iconIndex);
770 // iconIndex = -1; // for debug
771 AddComboBoxItem(name, iconIndex, 0, true);
772 }
773 AddComboBoxItem(name_Computer, iconIndex_Computer, 0, true);
774 {
775 FStringVector driveStrings;
776 MyGetLogicalDriveStrings(driveStrings);
777 FOR_VECTOR (i, driveStrings)
778 {
779 FString s = driveStrings[i];
780 ComboBoxPaths.Add(fs2us(s));
781 int iconIndex2 = GetRealIconIndex_for_DirPath(s, FILE_ATTRIBUTE_DIRECTORY);
782 if (!s.IsEmpty())
783 {
784 const FChar c = s.Back();
785 if (IS_PATH_SEPAR(c))
786 s.DeleteBack();
787 }
788 // iconIndex2 = -1; // for debug
789 AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
790 }
791 }
792 {
793 int iconIndex;
794 const UString name = RootFolder_GetName_Network(iconIndex);
795 AddComboBoxItem(name, iconIndex, 0, true);
796 }
797
798#endif
590 799
591 return false; 800 return false;
592 } 801 }
@@ -596,10 +805,10 @@ bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
596 int index = _headerComboBox.GetCurSel(); 805 int index = _headerComboBox.GetCurSel();
597 if (index >= 0) 806 if (index >= 0)
598 { 807 {
599 UString pass = ComboBoxPaths[index]; 808 const UString path = ComboBoxPaths[index];
600 _headerComboBox.SetCurSel(-1); 809 _headerComboBox.SetCurSel(-1);
601 // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse. 810 // _headerComboBox.SetText(pass); // it's fix for selecting by mouse.
602 if (BindToPathAndRefresh(pass) == S_OK) 811 if (BindToPathAndRefresh(path) == S_OK)
603 { 812 {
604 PostMsg(kSetFocusToListView); 813 PostMsg(kSetFocusToListView);
605 #ifdef UNDER_CE 814 #ifdef UNDER_CE
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp
index 2335fc0..544e9bf 100644
--- a/CPP/7zip/UI/FileManager/PanelItems.cpp
+++ b/CPP/7zip/UI/FileManager/PanelItems.cpp
@@ -583,8 +583,13 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
583 int cursorIndex = -1; 583 int cursorIndex = -1;
584 584
585 CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex; 585 CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
586#if 1 // 0 : for debug local icons loading
586 if (!Is_Slow_Icon_Folder() || _showRealFileIcons) 587 if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
587 _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex); 588 _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
589#endif
590
591 const bool isFSDrivesFolder = IsFSDrivesFolder();
592 const bool isArcFolder = IsArcFolder();
588 593
589 if (!IsFSFolder()) 594 if (!IsFSFolder())
590 { 595 {
@@ -631,10 +636,11 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
631 #else 636 #else
632 item.pszText = LPSTR_TEXTCALLBACKW; 637 item.pszText = LPSTR_TEXTCALLBACKW;
633 #endif 638 #endif
634 const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY; 639 // const UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
635 item.iImage = _extToIconMap.GetIconIndex(attrib, itemName); 640 item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
641 // g_Ext_to_Icon_Map.GetIconIndex(attrib, itemName);
636 if (item.iImage < 0) 642 if (item.iImage < 0)
637 item.iImage = 0; 643 item.iImage = 0;
638 if (_listView.InsertItem(&item) == -1) 644 if (_listView.InsertItem(&item) == -1)
639 return E_FAIL; 645 return E_FAIL;
640 listViewItemCount++; 646 listViewItemCount++;
@@ -755,11 +761,52 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
755 } 761 }
756 762
757 bool defined = false; 763 bool defined = false;
764 item.iImage = -1;
758 765
759 if (folderGetSystemIconIndex) 766 if (folderGetSystemIconIndex)
760 { 767 {
761 folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage); 768 const HRESULT res = folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
762 defined = (item.iImage > 0); 769 if (res == S_OK)
770 {
771 // item.iImage = -1; // for debug
772 defined = (item.iImage > 0);
773#if 0 // 0: can be slower: 2 attempts for some paths.
774 // 1: faster, but we can get default icon for some cases (where non default icon is possible)
775
776 if (item.iImage == 0)
777 {
778 // (item.iImage == 0) means default icon.
779 // But (item.iImage == 0) also can be returned for exe/ico files,
780 // if filePath is LONG PATH (path_len() >= MAX_PATH).
781 // Also we want to show split icon (.001) for any split extension: 001 002 003.
782 // Are there another cases for (item.iImage == 0) for files with known extensions?
783 // We don't want to do second attempt to request icon,
784 // if it also will return (item.iImage == 0).
785
786 int dotPos = -1;
787 for (unsigned k = 0;; k++)
788 {
789 const wchar_t c = name[k];
790 if (c == 0)
791 break;
792 if (c == '.')
793 dotPos = (int)i;
794 // we don't need IS_PATH_SEPAR check, because we have only (fileName) doesn't include path prefix.
795 // if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;
796 }
797 defined = true;
798 if (dotPos >= 0)
799 {
800#if 0
801 const wchar_t *ext = name + dotPos;
802 if (StringsAreEqualNoCase_Ascii(ext, ".exe") ||
803 StringsAreEqualNoCase_Ascii(ext, ".ico"))
804#endif
805 defined = false;
806 }
807 }
808#endif
809 }
763 } 810 }
764 811
765 if (!defined) 812 if (!defined)
@@ -769,26 +816,37 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
769 NCOM::CPropVariant prop; 816 NCOM::CPropVariant prop;
770 RINOK(_folder->GetProperty(i, kpidAttrib, &prop)) 817 RINOK(_folder->GetProperty(i, kpidAttrib, &prop))
771 if (prop.vt == VT_UI4) 818 if (prop.vt == VT_UI4)
819 {
772 attrib = prop.ulVal; 820 attrib = prop.ulVal;
821 if (isArcFolder)
822 {
823 // if attrib (high 16-bits) is supposed from posix,
824 // we keep only low bits (basic Windows attrib flags):
825 if (attrib & 0xF0000000)
826 attrib &= 0x3FFF;
827 }
828 }
773 } 829 }
774 if (IsItem_Folder(i)) 830 if (IsItem_Folder(i))
775 attrib |= FILE_ATTRIBUTE_DIRECTORY; 831 attrib |= FILE_ATTRIBUTE_DIRECTORY;
776
777 if (_currentFolderPrefix.IsEmpty())
778 {
779 int iconIndexTemp;
780 GetRealIconIndex(us2fs((UString)name) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);
781 item.iImage = iconIndexTemp;
782 }
783 else 832 else
833 attrib &= ~(UInt32)FILE_ATTRIBUTE_DIRECTORY;
834
835 item.iImage = -1;
836 if (isFSDrivesFolder)
784 { 837 {
785 item.iImage = _extToIconMap.GetIconIndex(attrib, name); 838 FString fs (us2fs((UString)name));
839 fs.Add_PathSepar();
840 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(fs, attrib);
841 // item.iImage = 0; // for debug
786 } 842 }
843 if (item.iImage < 0) // <= 0 check?
844 item.iImage = g_Ext_to_Icon_Map.GetIconIndex(attrib, name);
787 } 845 }
788 846
847 // item.iImage = -1; // for debug
789 if (item.iImage < 0) 848 if (item.iImage < 0)
790 item.iImage = 0; 849 item.iImage = 0; // default image
791
792 if (_listView.InsertItem(&item) == -1) 850 if (_listView.InsertItem(&item) == -1)
793 return E_FAIL; 851 return E_FAIL;
794 listViewItemCount++; 852 listViewItemCount++;
@@ -858,8 +916,8 @@ HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
858 sprintf(s, 916 sprintf(s,
859 // "attribMap = %5d, extMap = %5d, " 917 // "attribMap = %5d, extMap = %5d, "
860 "delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d", 918 "delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d",
861 // _extToIconMap._attribMap.Size(), 919 // g_Ext_to_Icon_Map._attribMap.Size(),
862 // _extToIconMap._extMap.Size(), 920 // g_Ext_to_Icon_Map._extMap.Size(),
863 tickCount1 - tickCount0, 921 tickCount1 - tickCount0,
864 tickCount2 - tickCount1, 922 tickCount2 - tickCount1,
865 tickCount3 - tickCount2, 923 tickCount3 - tickCount2,
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
index 606fb7f..192f660 100644
--- a/CPP/7zip/UI/FileManager/RootFolder.cpp
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -54,9 +54,9 @@ UString RootFolder_GetName_Computer(int &iconIndex);
54UString RootFolder_GetName_Computer(int &iconIndex) 54UString RootFolder_GetName_Computer(int &iconIndex)
55{ 55{
56 #ifdef USE_WIN_PATHS 56 #ifdef USE_WIN_PATHS
57 iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES); 57 iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
58 #else 58 #else
59 GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex); 59 iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY);
60 #endif 60 #endif
61 return LangString(IDS_COMPUTER); 61 return LangString(IDS_COMPUTER);
62} 62}
@@ -64,14 +64,14 @@ UString RootFolder_GetName_Computer(int &iconIndex)
64UString RootFolder_GetName_Network(int &iconIndex); 64UString RootFolder_GetName_Network(int &iconIndex);
65UString RootFolder_GetName_Network(int &iconIndex) 65UString RootFolder_GetName_Network(int &iconIndex)
66{ 66{
67 iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK); 67 iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_NETWORK);
68 return LangString(IDS_NETWORK); 68 return LangString(IDS_NETWORK);
69} 69}
70 70
71UString RootFolder_GetName_Documents(int &iconIndex); 71UString RootFolder_GetName_Documents(int &iconIndex);
72UString RootFolder_GetName_Documents(int &iconIndex) 72UString RootFolder_GetName_Documents(int &iconIndex)
73{ 73{
74 iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL); 74 iconIndex = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_PERSONAL);
75 return LangString(IDS_DOCUMENTS); 75 return LangString(IDS_DOCUMENTS);
76} 76}
77 77
@@ -96,7 +96,7 @@ void CRootFolder::Init()
96 _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]); 96 _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
97 _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]); 97 _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
98 _names[ROOT_INDEX_VOLUMES] = kVolPrefix; 98 _names[ROOT_INDEX_VOLUMES] = kVolPrefix;
99 _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES); 99 _iconIndices[ROOT_INDEX_VOLUMES] = Shell_GetFileInfo_SysIconIndex_for_CSIDL(CSIDL_DRIVES);
100 #endif 100 #endif
101} 101}
102 102
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
index c893ea9..406c9e1 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.cpp
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -20,16 +20,19 @@
20extern bool g_IsNT; 20extern bool g_IsNT;
21#endif 21#endif
22 22
23int GetIconIndexForCSIDL(int csidl) 23CExtToIconMap g_Ext_to_Icon_Map;
24
25int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)
24{ 26{
25 LPITEMIDLIST pidl = NULL; 27 LPITEMIDLIST pidl = NULL;
26 SHGetSpecialFolderLocation(NULL, csidl, &pidl); 28 SHGetSpecialFolderLocation(NULL, csidl, &pidl);
27 if (pidl) 29 if (pidl)
28 { 30 {
29 SHFILEINFO shellInfo; 31 SHFILEINFO shFileInfo;
30 shellInfo.iIcon = 0; 32 shFileInfo.iIcon = -1;
31 const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL, 33 const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl),
32 &shellInfo, sizeof(shellInfo), 34 FILE_ATTRIBUTE_DIRECTORY,
35 &shFileInfo, sizeof(shFileInfo),
33 SHGFI_PIDL | SHGFI_SYSICONINDEX); 36 SHGFI_PIDL | SHGFI_SYSICONINDEX);
34 /* 37 /*
35 IMalloc *pMalloc; 38 IMalloc *pMalloc;
@@ -43,9 +46,9 @@ int GetIconIndexForCSIDL(int csidl)
43 // we use OLE2.dll function here 46 // we use OLE2.dll function here
44 CoTaskMemFree(pidl); 47 CoTaskMemFree(pidl);
45 if (res) 48 if (res)
46 return shellInfo.iIcon; 49 return shFileInfo.iIcon;
47 } 50 }
48 return 0; 51 return -1;
49} 52}
50 53
51#ifndef _UNICODE 54#ifndef _UNICODE
@@ -60,69 +63,111 @@ static struct C_SHGetFileInfo_Init
60 f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS( 63 f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(
61 Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"), 64 Func_SHGetFileInfoW, ::GetModuleHandleW(L"shell32.dll"),
62 "SHGetFileInfoW"); 65 "SHGetFileInfoW");
66 // f_SHGetFileInfoW = NULL; // for debug
63 } 67 }
64} g_SHGetFileInfo_Init; 68} g_SHGetFileInfo_Init;
65#endif 69#endif
66 70
71#ifdef _UNICODE
72#define My_SHGetFileInfoW SHGetFileInfoW
73#else
67static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) 74static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
68{ 75{
69 #ifdef _UNICODE
70 return SHGetFileInfo
71 #else
72 if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW) 76 if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)
73 return 0; 77 return 0;
74 return g_SHGetFileInfo_Init.f_SHGetFileInfoW 78 return g_SHGetFileInfo_Init.f_SHGetFileInfoW(pszPath, attrib, psfi, cbFileInfo, uFlags);
75 #endif
76 (pszPath, attrib, psfi, cbFileInfo, uFlags);
77} 79}
80#endif
78 81
79DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) 82DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
83 CFSTR path, DWORD attrib, int &iconIndex)
80{ 84{
81 #ifndef _UNICODE 85#ifndef _UNICODE
82 if (!g_IsNT) 86 if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW)
83 { 87 {
84 SHFILEINFO shellInfo; 88 SHFILEINFO shFileInfo;
85 const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 89 // ZeroMemory(&shFileInfo, sizeof(shFileInfo));
86 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); 90 shFileInfo.iIcon = -1; // optional
87 iconIndex = shellInfo.iIcon; 91 const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path),
92 attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
93 &shFileInfo, sizeof(shFileInfo),
94 SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
95 iconIndex = shFileInfo.iIcon;
88 return res; 96 return res;
89 } 97 }
90 else 98 else
91 #endif 99#endif
92 { 100 {
93 SHFILEINFOW shellInfo; 101 SHFILEINFOW shFileInfo;
94 const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 102 // ZeroMemory(&shFileInfo, sizeof(shFileInfo));
95 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX); 103 shFileInfo.iIcon = -1; // optional
96 iconIndex = shellInfo.iIcon; 104 const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path),
105 attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,
106 &shFileInfo, sizeof(shFileInfo),
107 SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
108 // (shFileInfo.iIcon == 0) returned for unknown extensions and files without extension
109 iconIndex = shFileInfo.iIcon;
110 // we use SHGFI_USEFILEATTRIBUTES, and
111 // (res != 0) is expected for main cases, even if there are no such file.
112 // (res == 0) for path with kSuperPrefix \\?\
113 // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe.
114 // So we can use SHGFI_USEFILEATTRIBUTES for any case.
115 // UString temp = fs2us(path); // for debug
116 // UString tempName = temp.Ptr(temp.ReverseFind_PathSepar() + 1); // for debug
117 // iconIndex = -1; // for debug
97 return res; 118 return res;
98 } 119 }
99} 120}
100 121
122int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib)
123{
124 int iconIndex = -1;
125 if (!Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
126 path, attrib, iconIndex))
127 iconIndex = -1;
128 return iconIndex;
129}
130
131
132HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
133 CFSTR path, DWORD attrib, Int32 *iconIndex)
134{
135 *iconIndex = -1;
136 int iconIndexTemp;
137 if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
138 path, attrib, iconIndexTemp))
139 {
140 *iconIndex = iconIndexTemp;
141 return S_OK;
142 }
143 return GetLastError_noZero_HRESULT();
144}
145
101/* 146/*
102DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) 147DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
103{ 148{
104 #ifndef _UNICODE 149 #ifndef _UNICODE
105 if (!g_IsNT) 150 if (!g_IsNT)
106 { 151 {
107 SHFILEINFO shellInfo; 152 SHFILEINFO shFileInfo;
108 shellInfo.szTypeName[0] = 0; 153 shFileInfo.szTypeName[0] = 0;
109 DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 154 DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
110 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); 155 sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
111 if (typeName) 156 if (typeName)
112 *typeName = GetUnicodeString(shellInfo.szTypeName); 157 *typeName = GetUnicodeString(shFileInfo.szTypeName);
113 iconIndex = shellInfo.iIcon; 158 iconIndex = shFileInfo.iIcon;
114 return res; 159 return res;
115 } 160 }
116 else 161 else
117 #endif 162 #endif
118 { 163 {
119 SHFILEINFOW shellInfo; 164 SHFILEINFOW shFileInfo;
120 shellInfo.szTypeName[0] = 0; 165 shFileInfo.szTypeName[0] = 0;
121 DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo, 166 DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,
122 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME); 167 sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
123 if (typeName) 168 if (typeName)
124 *typeName = shellInfo.szTypeName; 169 *typeName = shFileInfo.szTypeName;
125 iconIndex = shellInfo.iIcon; 170 iconIndex = shFileInfo.iIcon;
126 return res; 171 return res;
127 } 172 }
128} 173}
@@ -164,6 +209,9 @@ static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar
164 return -1; 209 return -1;
165} 210}
166 211
212
213// bool DoItemAlwaysStart(const UString &name);
214
167int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) 215int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
168{ 216{
169 int dotPos = -1; 217 int dotPos = -1;
@@ -175,6 +223,8 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
175 break; 223 break;
176 if (c == '.') 224 if (c == '.')
177 dotPos = (int)i; 225 dotPos = (int)i;
226 // we don't need IS_PATH_SEPAR check, because (fileName) doesn't include path prefix.
227 // if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;
178 } 228 }
179 229
180 /* 230 /*
@@ -187,8 +237,11 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
187 } 237 }
188 */ 238 */
189 239
190 if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0) 240 if ((attrib & FILE_ATTRIBUTE_DIRECTORY) || dotPos < 0)
241 for (unsigned k = 0;; k++)
191 { 242 {
243 if (k >= 2)
244 return -1;
192 unsigned insertPos = 0; 245 unsigned insertPos = 0;
193 const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos); 246 const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
194 if (index >= 0) 247 if (index >= 0)
@@ -197,33 +250,43 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
197 return _attribMap[(unsigned)index].IconIndex; 250 return _attribMap[(unsigned)index].IconIndex;
198 } 251 }
199 CAttribIconPair pair; 252 CAttribIconPair pair;
200 GetRealIconIndex( 253 pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
201 #ifdef UNDER_CE 254 #ifdef UNDER_CE
202 FTEXT("\\") 255 FTEXT("\\")
203 #endif 256 #endif
204 FTEXT("__DIR__") 257 FTEXT("__DIR__")
205 , attrib, pair.IconIndex 258 , attrib
206 // , pair.TypeName 259 // , pair.TypeName
207 ); 260 );
208 261 if (_attribMap.Size() < (1u << 16) // we limit cache size
209 /* 262 || attrib < (1u << 15)) // we want to put all items with basic attribs to cache
210 char s[256]; 263 {
211 sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib); 264 /*
212 OutputDebugStringA(s); 265 char s[256];
213 */ 266 sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
214 267 OutputDebugStringA(s);
215 pair.Attrib = attrib; 268 */
216 _attribMap.Insert(insertPos, pair); 269 pair.Attrib = attrib;
217 // if (typeName) *typeName = pair.TypeName; 270 _attribMap.Insert(insertPos, pair);
218 return pair.IconIndex; 271 // if (typeName) *typeName = pair.TypeName;
272 return pair.IconIndex;
273 }
274 if (pair.IconIndex >= 0)
275 return pair.IconIndex;
276 attrib = (attrib & FILE_ATTRIBUTE_DIRECTORY) ?
277 FILE_ATTRIBUTE_DIRECTORY :
278 FILE_ATTRIBUTE_ARCHIVE;
219 } 279 }
220 280
281 CObjectVector<CExtIconPair> &map =
282 (attrib & FILE_ATTRIBUTE_COMPRESSED) ?
283 _extMap_Compressed : _extMap_Normal;
221 const wchar_t *ext = fileName + dotPos + 1; 284 const wchar_t *ext = fileName + dotPos + 1;
222 unsigned insertPos = 0; 285 unsigned insertPos = 0;
223 const int index = FindInSorted_Ext(_extMap, ext, insertPos); 286 const int index = FindInSorted_Ext(map, ext, insertPos);
224 if (index >= 0) 287 if (index >= 0)
225 { 288 {
226 const CExtIconPair &pa = _extMap[index]; 289 const CExtIconPair &pa = map[index];
227 // if (typeName) *typeName = pa.TypeName; 290 // if (typeName) *typeName = pa.TypeName;
228 return pa.IconIndex; 291 return pa.IconIndex;
229 } 292 }
@@ -238,14 +301,14 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
238 } 301 }
239 if (i != 0 && ext[i] == 0) 302 if (i != 0 && ext[i] == 0)
240 { 303 {
241 // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003 304 // Shell_GetFileInfo_SysIconIndex_for_Path is too slow for big number of split extensions: .001, .002, .003
242 if (!SplitIconIndex_Defined) 305 if (!SplitIconIndex_Defined)
243 { 306 {
244 GetRealIconIndex( 307 Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
245 #ifdef UNDER_CE 308 #ifdef UNDER_CE
246 FTEXT("\\") 309 FTEXT("\\")
247 #endif 310 #endif
248 FTEXT("__FILE__.001"), 0, SplitIconIndex); 311 FTEXT("__FILE__.001"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex);
249 SplitIconIndex_Defined = true; 312 SplitIconIndex_Defined = true;
250 } 313 }
251 return SplitIconIndex; 314 return SplitIconIndex;
@@ -253,27 +316,36 @@ int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UStrin
253 316
254 CExtIconPair pair; 317 CExtIconPair pair;
255 pair.Ext = ext; 318 pair.Ext = ext;
256 GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex); 319 pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(
257 _extMap.Insert(insertPos, pair); 320 us2fs(fileName + dotPos),
321 attrib & FILE_ATTRIBUTE_COMPRESSED ?
322 FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED:
323 FILE_ATTRIBUTE_ARCHIVE);
324 if (map.Size() < (1u << 16) // we limit cache size
325 // || DoItemAlwaysStart(fileName + dotPos) // we want some popular extensions in cache
326 )
327 map.Insert(insertPos, pair);
258 // if (typeName) *typeName = pair.TypeName; 328 // if (typeName) *typeName = pair.TypeName;
259 return pair.IconIndex; 329 return pair.IconIndex;
260} 330}
261 331
262/*
263int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
264{
265 return GetIconIndex(attrib, fileName, NULL);
266}
267*/
268 332
269HIMAGELIST GetSysImageList(bool smallIcons) 333HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons)
270{ 334{
271 SHFILEINFO shellInfo; 335 SHFILEINFO shFileInfo;
272 return (HIMAGELIST)SHGetFileInfo(TEXT(""), 336 // shFileInfo.hIcon = NULL; // optional
273 FILE_ATTRIBUTE_NORMAL | 337 const DWORD_PTR res = SHGetFileInfo(TEXT(""),
338 /* FILE_ATTRIBUTE_ARCHIVE | */
274 FILE_ATTRIBUTE_DIRECTORY, 339 FILE_ATTRIBUTE_DIRECTORY,
275 &shellInfo, sizeof(shellInfo), 340 &shFileInfo, sizeof(shFileInfo),
276 SHGFI_USEFILEATTRIBUTES | 341 SHGFI_USEFILEATTRIBUTES |
277 SHGFI_SYSICONINDEX | 342 SHGFI_SYSICONINDEX |
278 (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON)); 343 (smallIcons ? SHGFI_SMALLICON : SHGFI_LARGEICON));
344#if 0
345 // (shFileInfo.hIcon == NULL), because we don't use SHGFI_ICON.
346 // so DestroyIcon() is not required
347 if (res && shFileInfo.hIcon) // unexpected
348 DestroyIcon(shFileInfo.hIcon);
349#endif
350 return (HIMAGELIST)res;
279} 351}
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
index 1d34ef6..975ce25 100644
--- a/CPP/7zip/UI/FileManager/SysIconUtils.h
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -14,7 +14,6 @@ struct CExtIconPair
14 UString Ext; 14 UString Ext;
15 int IconIndex; 15 int IconIndex;
16 // UString TypeName; 16 // UString TypeName;
17
18 // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); } 17 // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
19}; 18};
20 19
@@ -23,15 +22,15 @@ struct CAttribIconPair
23 DWORD Attrib; 22 DWORD Attrib;
24 int IconIndex; 23 int IconIndex;
25 // UString TypeName; 24 // UString TypeName;
26
27 // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); } 25 // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
28}; 26};
29 27
30class CExtToIconMap 28
29struct CExtToIconMap
31{ 30{
32public:
33 CRecordVector<CAttribIconPair> _attribMap; 31 CRecordVector<CAttribIconPair> _attribMap;
34 CObjectVector<CExtIconPair> _extMap; 32 CObjectVector<CExtIconPair> _extMap_Normal;
33 CObjectVector<CExtIconPair> _extMap_Compressed;
35 int SplitIconIndex; 34 int SplitIconIndex;
36 int SplitIconIndex_Defined; 35 int SplitIconIndex_Defined;
37 36
@@ -40,16 +39,27 @@ public:
40 void Clear() 39 void Clear()
41 { 40 {
42 SplitIconIndex_Defined = false; 41 SplitIconIndex_Defined = false;
43 _extMap.Clear(); 42 _extMap_Normal.Clear();
43 _extMap_Compressed.Clear();
44 _attribMap.Clear(); 44 _attribMap.Clear();
45 } 45 }
46 int GetIconIndex_DIR(DWORD attrib = FILE_ATTRIBUTE_DIRECTORY)
47 {
48 return GetIconIndex(attrib, L"__DIR__");
49 }
46 int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */); 50 int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);
47 // int GetIconIndex(DWORD attrib, const UString &fileName);
48}; 51};
49 52
50DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex); 53extern CExtToIconMap g_Ext_to_Icon_Map;
51int GetIconIndexForCSIDL(int csidl); 54
55DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(
56 CFSTR path, DWORD attrib, int &iconIndex);
57HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(
58 CFSTR path, DWORD attrib, Int32 *iconIndex);
59int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib);
60
61int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl);
52 62
53HIMAGELIST GetSysImageList(bool smallIcons); 63HIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons);
54 64
55#endif 65#endif
diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp
index f1353b8..c1ca643 100644
--- a/CPP/7zip/UI/FileManager/VerCtrl.cpp
+++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp
@@ -387,13 +387,13 @@ void CApp::VerCtrl(unsigned id)
387 */ 387 */
388 COverwriteDialog dialog; 388 COverwriteDialog dialog;
389 389
390 dialog.OldFileInfo.SetTime(&fdi.Info.ftLastWriteTime); 390 dialog.OldFileInfo.SetTime(fdi.Info.ftLastWriteTime);
391 dialog.OldFileInfo.SetSize(fdi.GetSize()); 391 dialog.OldFileInfo.SetSize(fdi.GetSize());
392 dialog.OldFileInfo.Name = fs2us(path); 392 dialog.OldFileInfo.Path = fs2us(path);
393 393
394 dialog.NewFileInfo.SetTime(&fdi2.Info.ftLastWriteTime); 394 dialog.NewFileInfo.SetTime(fdi2.Info.ftLastWriteTime);
395 dialog.NewFileInfo.SetSize(fdi2.GetSize()); 395 dialog.NewFileInfo.SetSize(fdi2.GetSize());
396 dialog.NewFileInfo.Name = fs2us(path2); 396 dialog.NewFileInfo.Path = fs2us(path2);
397 397
398 dialog.ShowExtraButtons = false; 398 dialog.ShowExtraButtons = false;
399 dialog.DefaultButton_is_NO = true; 399 dialog.DefaultButton_is_NO = true;
diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp
index b96e413..231bab5 100644
--- a/CPP/7zip/UI/GUI/HashGUI.cpp
+++ b/CPP/7zip/UI/GUI/HashGUI.cpp
@@ -66,28 +66,6 @@ void AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
66} 66}
67 67
68 68
69void AddSizeValue(UString &s, UInt64 value)
70{
71 {
72 wchar_t sz[32];
73 ConvertUInt64ToString(value, sz);
74 s += MyFormatNew(IDS_FILE_SIZE, sz);
75 }
76 if (value >= (1 << 10))
77 {
78 char c;
79 if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }
80 else if (value >= (10 << 20)) { value >>= 20; c = 'M'; }
81 else { value >>= 10; c = 'K'; }
82
83 s += " (";
84 s.Add_UInt64(value);
85 s.Add_Space();
86 s += (wchar_t)c;
87 s += "iB)";
88 }
89}
90
91void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value) 69void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value)
92{ 70{
93 CProperty &pair = pairs.AddNew(); 71 CProperty &pair = pairs.AddNew();
diff --git a/CPP/Windows/FileSystem.cpp b/CPP/Windows/FileSystem.cpp
index d11f02e..b402306 100644
--- a/CPP/Windows/FileSystem.cpp
+++ b/CPP/Windows/FileSystem.cpp
@@ -157,6 +157,31 @@ bool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize,
157 157
158#endif 158#endif
159 159
160/*
161bool Is_File_LimitedBy_4GB(CFSTR _path, bool &isFsDetected)
162{
163 isFsDetected = false;
164 FString path (_path);
165 path.DeleteFrom(NName::GetRootPrefixSize(path));
166 // GetVolumeInformation supports super paths.
167 // NName::If_IsSuperPath_RemoveSuperPrefix(path);
168 if (!path.IsEmpty())
169 {
170 DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags;
171 UString volName, fileSystemName;
172 if (MyGetVolumeInformation(path, volName,
173 &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags,
174 fileSystemName))
175 {
176 isFsDetected = true;
177 if (fileSystemName.IsPrefixedBy_Ascii_NoCase("fat"))
178 return true;
179 }
180 }
181 return false;
182}
183*/
184
160}}} 185}}}
161 186
162#endif 187#endif
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp
index d23e84b..cfc6a90 100644
--- a/CPP/Windows/SystemInfo.cpp
+++ b/CPP/Windows/SystemInfo.cpp
@@ -5,6 +5,7 @@
5#include "../../C/CpuArch.h" 5#include "../../C/CpuArch.h"
6 6
7#include "../Common/IntToString.h" 7#include "../Common/IntToString.h"
8#include "../Common/StringConvert.h"
8 9
9#ifdef _WIN32 10#ifdef _WIN32
10 11
@@ -511,8 +512,6 @@ void GetSysInfo(AString &s1, AString &s2)
511} 512}
512 513
513 514
514void GetCpuName(AString &s);
515
516static void AddBracedString(AString &dest, AString &src) 515static void AddBracedString(AString &dest, AString &src)
517{ 516{
518 if (!src.IsEmpty()) 517 if (!src.IsEmpty())
@@ -554,9 +553,7 @@ void CCpuName::Fill()
554 #ifdef MY_CPU_X86_OR_AMD64 553 #ifdef MY_CPU_X86_OR_AMD64
555 { 554 {
556 #if !defined(MY_CPU_AMD64) 555 #if !defined(MY_CPU_AMD64)
557 if (!z7_x86_cpuid_GetMaxFunc()) 556 if (z7_x86_cpuid_GetMaxFunc())
558 s += "x86";
559 else
560 #endif 557 #endif
561 { 558 {
562 x86cpuid_to_String(s); 559 x86cpuid_to_String(s);
@@ -583,43 +580,26 @@ void CCpuName::Fill()
583 #endif 580 #endif
584 581
585 582
586 if (s.IsEmpty()) 583#ifdef _WIN32
587 {
588 #ifdef MY_CPU_LE
589 s += "LE";
590 #elif defined(MY_CPU_BE)
591 s += "BE";
592 #endif
593 }
594
595 #ifdef __APPLE__
596 {
597 AString s2;
598 UInt32 v = 0;
599 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
600 {
601 s2.Add_UInt32(v);
602 s2 += 'C';
603 }
604 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
605 {
606 s2.Add_UInt32(v);
607 s2 += 'T';
608 }
609 if (!s2.IsEmpty())
610 {
611 s.Add_Space_if_NotEmpty();
612 s += s2;
613 }
614 }
615 #endif
616
617
618 #ifdef _WIN32
619 { 584 {
620 NRegistry::CKey key; 585 NRegistry::CKey key;
621 if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS) 586 if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
622 { 587 {
588 // s.Empty(); // for debug
589 {
590 CSysString name;
591 if (s.IsEmpty())
592 if (key.QueryValue(TEXT("ProcessorNameString"), name) == ERROR_SUCCESS)
593 {
594 s += GetAnsiString(name);
595 }
596 if (key.QueryValue(TEXT("Identifier"), name) == ERROR_SUCCESS)
597 {
598 if (!Revision.IsEmpty())
599 Revision += " : ";
600 Revision += GetAnsiString(name);
601 }
602 }
623 LONG res[2]; 603 LONG res[2];
624 CByteBuffer bufs[2]; 604 CByteBuffer bufs[2];
625 { 605 {
@@ -627,8 +607,9 @@ void CCpuName::Fill()
627 { 607 {
628 UInt32 size = 0; 608 UInt32 size = 0;
629 res[i] = key.QueryValue(i == 0 ? 609 res[i] = key.QueryValue(i == 0 ?
630 TEXT("Previous Update Revision") : 610 TEXT("Previous Update Revision") :
631 TEXT("Update Revision"), bufs[i], size); 611 TEXT("Update Revision"),
612 bufs[i], size);
632 if (res[i] == ERROR_SUCCESS) 613 if (res[i] == ERROR_SUCCESS)
633 if (size != bufs[i].Size()) 614 if (size != bufs[i].Size())
634 res[i] = ERROR_SUCCESS + 1; 615 res[i] = ERROR_SUCCESS + 1;
@@ -657,8 +638,36 @@ void CCpuName::Fill()
657 } 638 }
658 } 639 }
659 } 640 }
660 #endif 641#endif
661 642
643 if (s.IsEmpty())
644 {
645 #ifdef MY_CPU_NAME
646 s += MY_CPU_NAME;
647 #endif
648 }
649
650 #ifdef __APPLE__
651 {
652 AString s2;
653 UInt32 v = 0;
654 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
655 {
656 s2.Add_UInt32(v);
657 s2.Add_Char('C');
658 }
659 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
660 {
661 s2.Add_UInt32(v);
662 s2.Add_Char('T');
663 }
664 if (!s2.IsEmpty())
665 {
666 s.Add_Space_if_NotEmpty();
667 s += s2;
668 }
669 }
670 #endif
662 671
663 #ifdef Z7_LARGE_PAGES 672 #ifdef Z7_LARGE_PAGES
664 Add_LargePages_String(LargePages); 673 Add_LargePages_String(LargePages);
@@ -900,7 +909,7 @@ void GetSystemInfoText(AString &sRes)
900 } 909 }
901 { 910 {
902 AString s; 911 AString s;
903 GetCpuName(s); 912 GetCpuName_MultiLine(s);
904 if (!s.IsEmpty()) 913 if (!s.IsEmpty())
905 { 914 {
906 sRes += s; 915 sRes += s;
@@ -923,18 +932,6 @@ void GetSystemInfoText(AString &sRes)
923} 932}
924 933
925 934
926void GetCpuName(AString &s);
927void GetCpuName(AString &s)
928{
929 CCpuName cpuName;
930 cpuName.Fill();
931 s = cpuName.CpuName;
932 AString s2;
933 cpuName.Get_Revision_Microcode_LargePages(s2);
934 s.Add_OptSpaced(s2);
935}
936
937
938void GetCpuName_MultiLine(AString &s); 935void GetCpuName_MultiLine(AString &s);
939void GetCpuName_MultiLine(AString &s) 936void GetCpuName_MultiLine(AString &s)
940{ 937{