diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-08-11 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-08-12 16:50:32 +0500 |
| commit | e008ce3976c087bfd21344af8f00a23cf69d4174 (patch) | |
| tree | 17e556c773ed443dba6c659ec6ea1556f955d169 /CPP | |
| parent | a7a1d4a241492e81f659a920f7379c193593ebc6 (diff) | |
| download | 7zip-24.08.tar.gz 7zip-24.08.tar.bz2 7zip-24.08.zip | |
24.0824.08
Diffstat (limited to '')
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 | { |
