diff options
Diffstat (limited to 'CPP')
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[] = | |||
628 | static const CUInt32PCharPair g_MachinePairs[] = | 628 | static 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_* | ||
185 | static 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 | |||
183 | enum | 204 | enum |
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 | ||
276 | bool COptHeader::Parse(const Byte *p, UInt32 size) | 300 | bool 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 | ||
840 | static const CStatProp kArcProps[] = | 887 | static 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 | |||
875 | static const Byte kProps[] = | 924 | static 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 | ||
886 | IMP_IInArchive_Props | 936 | IMP_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 | ||
1853 | static 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 | |||
1768 | static bool CompareWStrStrings(const Byte *p, const char *s) | 1863 | static 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 | ||
1900 | static 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 | |||
1805 | static const unsigned k_ResoureBlockHeader_Size = 6; | 1917 | static const unsigned k_ResoureBlockHeader_Size = 6; |
1806 | 1918 | ||
1807 | bool CVersionBlock::Parse(const Byte *p, UInt32 size) | 1919 | bool 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 § = _sections.AddNew(); | 2454 | CSection § = _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 § = _sections[mixItem.SectionIndex]; | 2933 | const CSection § = _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 | ||
26 | using namespace NWindows; | 27 | using namespace NWindows; |
27 | 28 | ||
@@ -32,9 +33,9 @@ static const Byte k_Signature[] = { 'Q', 'F', 'I', 0xFB, 0, 0, 0 }; | |||
32 | 33 | ||
33 | /* | 34 | /* |
34 | VA to PA maps: | 35 | VA 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 | ||
40 | Z7_class_CHandler_final: public CHandlerImg | 41 | Z7_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[] = | |||
274 | static const Byte kArcProps[] = | 261 | static 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 | ||
281 | IMP_IInArchive_Props | 271 | IMP_IInArchive_Props |
282 | IMP_IInArchive_ArcProps | 272 | IMP_IInArchive_ArcProps |
283 | 273 | ||
274 | static 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 | |||
284 | Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | 283 | Z7_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 | ||
356 | HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | 381 | HRESULT 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 | ||
22 | using namespace NWindows; | 22 | using namespace NWindows; |
23 | 23 | ||
24 | static const unsigned kNumWinAtrribFlags = 21; | 24 | static const unsigned kNumWinAtrribFlags = 30; |
25 | static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEV.X.PU"; | 25 | static const char g_WinAttribChars[kNumWinAtrribFlags + 1] = "RHS8DAdNTsLCOIEVvX.PU.M......B"; |
26 | 26 | ||
27 | /* | 27 | /* |
28 | FILE_ATTRIBUTE_ | 28 | FILE_ATTRIBUTE_ |
@@ -48,8 +48,9 @@ FILE_ATTRIBUTE_ | |||
48 | 18 RECALL_ON_OPEN or EA | 48 | 18 RECALL_ON_OPEN or EA |
49 | 19 PINNED | 49 | 19 PINNED |
50 | 20 UNPINNED | 50 | 20 UNPINNED |
51 | 21 STRICTLY_SEQUENTIAL | 51 | 21 STRICTLY_SEQUENTIAL (10.0.16267) |
52 | 22 RECALL_ON_DATA_ACCESS | 52 | 22 RECALL_ON_DATA_ACCESS |
53 | 29 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); | |||
534 | bool FindExt(const char *p, const UString &name, CStringFinder &finder) | 534 | bool 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 | |||
666 | Z7_COM7F_IMF(CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) | 666 | Z7_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 | ||
48 | static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize, | 48 | static 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 | ||
218 | Z7_COM7F_IMF(CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)) | 217 | Z7_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) | |||
268 | Z7_COM7F_IMF(CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)) | 267 | Z7_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 | ||
323 | Z7_COM7F_IMF(CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) | 322 | Z7_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 | ||
338 | void CFSDrives::AddExt(FString &s, unsigned index) const | 334 | void 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 | ||
1035 | Z7_COM7F_IMF(CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress)) | 1035 | Z7_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 | ||
1081 | Z7_COM7F_IMF(CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */)) | 1081 | Z7_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 | |||
1134 | Z7_COM7F_IMF(CFSFolder::SetProperty(UInt32 index, PROPID propID, | 1134 | Z7_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 | ||
1173 | Z7_COM7F_IMF(CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) | 1173 | Z7_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 | ||
1188 | Z7_COM7F_IMF(CFSFolder::SetFlatMode(Int32 flatMode)) | 1183 | Z7_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 | ||
23 | struct CDirItem: public NWindows::NFile::NFind::CFileInfo | 23 | struct 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 | ||
129 | private: | 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 | ||
255 | Z7_COM7F_IMF(CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)) | 255 | Z7_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 | ||
32 | static const unsigned kCurrentFileNameSizeLimit = 82; | 34 | static const unsigned kCurrentFileNameSizeLimit = 72; |
33 | static const unsigned kCurrentFileNameSizeLimit2 = 30; | ||
34 | 35 | ||
35 | void COverwriteDialog::ReduceString(UString &s) | 36 | void 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 | ||
51 | void COverwriteDialog::SetFileInfoControl(unsigned textID, unsigned iconID, | 57 | |
52 | const NOverwriteDialog::CFileInfo &fileInfo) | 58 | void 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 | |||
67 | void AddSizeValue(UString &s, UInt64 value); | ||
68 | void 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; | 90 | void 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 | |||
97 | bool COverwriteDialog::OnInit() | 232 | bool 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 | ||
266 | bool 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 | |||
125 | bool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) | 275 | bool 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 | ||
48 | class COverwriteDialog: public NWindows::NControl::CModalDialog | 58 | class 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 | ||
57 | public: | 71 | public: |
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: | |||
147 | struct CTempFileInfo | 147 | struct 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 | ||
172 | struct CFolderLink: public CTempFileInfo | 172 | struct 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 | ||
311 | class CPanel Z7_final: public NWindows::NControl::CWindow2 | 311 | class 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 | ||
371 | static int GetRealIconIndex(CFSTR path, DWORD attributes) | 371 | |
372 | |||
373 | static 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 | |||
384 | extern UString RootFolder_GetName_Computer(int &iconIndex); | ||
385 | extern UString RootFolder_GetName_Network(int &iconIndex); | ||
386 | extern UString RootFolder_GetName_Documents(int &iconIndex); | ||
387 | |||
388 | |||
389 | static 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 | |||
379 | void CPanel::LoadFullPathAndShow() | 406 | void 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 | ||
498 | void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList) | 592 | void 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 | ||
526 | extern UString RootFolder_GetName_Computer(int &iconIndex); | ||
527 | extern UString RootFolder_GetName_Network(int &iconIndex); | ||
528 | extern UString RootFolder_GetName_Documents(int &iconIndex); | ||
529 | 626 | ||
530 | bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) | 627 | bool 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); | |||
54 | UString RootFolder_GetName_Computer(int &iconIndex) | 54 | UString 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) | |||
64 | UString RootFolder_GetName_Network(int &iconIndex); | 64 | UString RootFolder_GetName_Network(int &iconIndex); |
65 | UString RootFolder_GetName_Network(int &iconIndex) | 65 | UString 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 | ||
71 | UString RootFolder_GetName_Documents(int &iconIndex); | 71 | UString RootFolder_GetName_Documents(int &iconIndex); |
72 | UString RootFolder_GetName_Documents(int &iconIndex) | 72 | UString 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 @@ | |||
20 | extern bool g_IsNT; | 20 | extern bool g_IsNT; |
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | int GetIconIndexForCSIDL(int csidl) | 23 | CExtToIconMap g_Ext_to_Icon_Map; |
24 | |||
25 | int 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 | ||
67 | static DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags) | 74 | static 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 | ||
79 | DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex) | 82 | DWORD_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 | ||
122 | int 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 | |||
132 | HRESULT 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 | /* |
102 | DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName) | 147 | DWORD_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 | |||
167 | int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */) | 215 | int 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 | /* | ||
263 | int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName) | ||
264 | { | ||
265 | return GetIconIndex(attrib, fileName, NULL); | ||
266 | } | ||
267 | */ | ||
268 | 332 | ||
269 | HIMAGELIST GetSysImageList(bool smallIcons) | 333 | HIMAGELIST 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 | ||
30 | class CExtToIconMap | 28 | |
29 | struct CExtToIconMap | ||
31 | { | 30 | { |
32 | public: | ||
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 | ||
50 | DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex); | 53 | extern CExtToIconMap g_Ext_to_Icon_Map; |
51 | int GetIconIndexForCSIDL(int csidl); | 54 | |
55 | DWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef( | ||
56 | CFSTR path, DWORD attrib, int &iconIndex); | ||
57 | HRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT( | ||
58 | CFSTR path, DWORD attrib, Int32 *iconIndex); | ||
59 | int Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib); | ||
60 | |||
61 | int Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl); | ||
52 | 62 | ||
53 | HIMAGELIST GetSysImageList(bool smallIcons); | 63 | HIMAGELIST 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 | ||
69 | void 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 | |||
91 | void AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value) | 69 | void 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 | /* | ||
161 | bool 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 | ||
514 | void GetCpuName(AString &s); | ||
515 | |||
516 | static void AddBracedString(AString &dest, AString &src) | 515 | static 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 | ||
926 | void GetCpuName(AString &s); | ||
927 | void 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 | |||
938 | void GetCpuName_MultiLine(AString &s); | 935 | void GetCpuName_MultiLine(AString &s); |
939 | void GetCpuName_MultiLine(AString &s) | 936 | void GetCpuName_MultiLine(AString &s) |
940 | { | 937 | { |