diff options
Diffstat (limited to 'CPP')
44 files changed, 1494 insertions, 810 deletions
diff --git a/CPP/7zip/7zip_gcc.mak b/CPP/7zip/7zip_gcc.mak index 12f1ef2..a78c0fa 100644 --- a/CPP/7zip/7zip_gcc.mak +++ b/CPP/7zip/7zip_gcc.mak | |||
| @@ -142,8 +142,8 @@ MY_MKDIR=mkdir | |||
| 142 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll | 142 | DEL_OBJ_EXE = -$(RM) $(O)\*.o $(O)\$(PROG).exe $(O)\$(PROG).dll |
| 143 | endif | 143 | endif |
| 144 | 144 | ||
| 145 | LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP) | 145 | LIB2_GUI = -lole32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 $(LIB_HTMLHELP) |
| 146 | LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) | 146 | LIB2 = -loleaut32 -luuid -ladvapi32 -luser32 $(LIB2_GUI) |
| 147 | 147 | ||
| 148 | # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files | 148 | # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files |
| 149 | # CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE | 149 | # CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE |
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp index c8c5d26..6ba04a2 100644 --- a/CPP/7zip/Archive/7z/7zUpdate.cpp +++ b/CPP/7zip/Archive/7z/7zUpdate.cpp | |||
| @@ -721,7 +721,7 @@ static int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param | |||
| 721 | return (u1.IsDir && u1.IsAnti) ? -n : n; | 721 | return (u1.IsDir && u1.IsAnti) ? -n : n; |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | static const char *g_Exts = | 724 | static const char * const g_Exts = |
| 725 | " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" | 725 | " 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo" |
| 726 | " zip jar ear war msi" | 726 | " zip jar ear war msi" |
| 727 | " 3gp avi mov mpeg mpg mpe wmv" | 727 | " 3gp avi mov mpeg mpg mpe wmv" |
diff --git a/CPP/7zip/Archive/ComHandler.cpp b/CPP/7zip/Archive/ComHandler.cpp index 144369e..40a5349 100644 --- a/CPP/7zip/Archive/ComHandler.cpp +++ b/CPP/7zip/Archive/ComHandler.cpp | |||
| @@ -2,41 +2,62 @@ | |||
| 2 | 2 | ||
| 3 | #include "StdAfx.h" | 3 | #include "StdAfx.h" |
| 4 | 4 | ||
| 5 | #include "../../../C/Alloc.h" | ||
| 6 | #include "../../../C/CpuArch.h" | 5 | #include "../../../C/CpuArch.h" |
| 7 | 6 | ||
| 8 | #include "../../Common/IntToString.h" | ||
| 9 | #include "../../Common/ComTry.h" | 7 | #include "../../Common/ComTry.h" |
| 10 | #include "../../Common/MyCom.h" | ||
| 11 | #include "../../Common/MyBuffer.h" | ||
| 12 | #include "../../Common/MyString.h" | ||
| 13 | 8 | ||
| 14 | #include "../../Windows/PropVariant.h" | 9 | #include "../../Windows/PropVariant.h" |
| 15 | 10 | ||
| 16 | #include "../Common/LimitedStreams.h" | 11 | #include "../Common/LimitedStreams.h" |
| 17 | #include "../Common/ProgressUtils.h" | 12 | #include "../Common/ProgressUtils.h" |
| 18 | #include "../Common/RegisterArc.h" | 13 | #include "../Common/RegisterArc.h" |
| 14 | #include "../Common/StreamObjects.h" | ||
| 19 | #include "../Common/StreamUtils.h" | 15 | #include "../Common/StreamUtils.h" |
| 20 | 16 | ||
| 21 | #include "../Compress/CopyCoder.h" | 17 | #include "../Compress/CopyCoder.h" |
| 22 | 18 | ||
| 23 | #define Get16(p) GetUi16(p) | 19 | #include "Common/ItemNameUtils.h" |
| 24 | #define Get32(p) GetUi32(p) | 20 | |
| 21 | #define Get16(p) GetUi16a(p) | ||
| 22 | #define Get32(p) GetUi32a(p) | ||
| 23 | |||
| 24 | // we don't expect to get deleted files in real files | ||
| 25 | // define Z7_COMPOUND_SHOW_DELETED for debug | ||
| 26 | // #define Z7_COMPOUND_SHOW_DELETED | ||
| 25 | 27 | ||
| 26 | namespace NArchive { | 28 | namespace NArchive { |
| 27 | namespace NCom { | 29 | namespace NCom { |
| 28 | 30 | ||
| 31 | static const unsigned k_Long_path_level_limit = 256; | ||
| 32 | |||
| 29 | static const Byte kSignature[] = | 33 | static const Byte kSignature[] = |
| 30 | { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }; | 34 | { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }; |
| 35 | |||
| 36 | // encoded "[!]MsiPatchSequence" name in "msp" file | ||
| 37 | static const Byte k_Sequence_msp[] = | ||
| 38 | { 0x40, 0x48, 0x96, 0x45, 0x6c, 0x3e, 0xe4, 0x45, | ||
| 39 | 0xe6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41, | ||
| 40 | 0x37, 0x41, 0, 0 }; | ||
| 41 | |||
| 42 | // encoded "MergeModule.CABinet" name in "msm" file | ||
| 43 | static const Byte k_Sequence_msm[] = | ||
| 44 | { 0x16, 0x42, 0xb5, 0x42, 0xa8, 0x3d, 0xf2, 0x41, | ||
| 45 | 0xf8, 0x43, 0xa8, 0x47, 0x8c, 0x3a, 0x0b, 0x43, | ||
| 46 | 0x31, 0x42, 0x37, 0x48, 0, 0 }; | ||
| 47 | |||
| 48 | // static const Byte k_CLSID_AAF_V3[] = { 0x41, 0x41, 0x46, 0x42, 0x0d, 0x00, 0x4f, 0x4d, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0xff }; | ||
| 49 | // static const Byte k_CLSID_AAF_V4[] = { 0x01, 0x02, 0x01, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x03, 0x02, 0x01, 0x01 }; | ||
| 31 | 50 | ||
| 32 | enum EType | 51 | enum EArcType |
| 33 | { | 52 | { |
| 34 | k_Type_Common, | 53 | k_Type_Common, |
| 35 | k_Type_Msi, | 54 | k_Type_Msi, |
| 36 | k_Type_Msp, | 55 | k_Type_Msp, |
| 56 | k_Type_Msm, | ||
| 37 | k_Type_Doc, | 57 | k_Type_Doc, |
| 38 | k_Type_Ppt, | 58 | k_Type_Ppt, |
| 39 | k_Type_Xls | 59 | k_Type_Xls, |
| 60 | k_Type_Aaf | ||
| 40 | }; | 61 | }; |
| 41 | 62 | ||
| 42 | static const char * const kExtensions[] = | 63 | static const char * const kExtensions[] = |
| @@ -44,35 +65,63 @@ static const char * const kExtensions[] = | |||
| 44 | "compound" | 65 | "compound" |
| 45 | , "msi" | 66 | , "msi" |
| 46 | , "msp" | 67 | , "msp" |
| 68 | , "msm" | ||
| 47 | , "doc" | 69 | , "doc" |
| 48 | , "ppt" | 70 | , "ppt" |
| 49 | , "xls" | 71 | , "xls" |
| 72 | , "aaf" | ||
| 50 | }; | 73 | }; |
| 51 | 74 | ||
| 52 | namespace NFatID | 75 | namespace NFatID |
| 53 | { | 76 | { |
| 54 | // static const UInt32 kFree = 0xFFFFFFFF; | 77 | static const UInt32 kFree = 0xffffffff; |
| 55 | static const UInt32 kEndOfChain = 0xFFFFFFFE; | 78 | static const UInt32 kEndOfChain = 0xfffffffe; |
| 56 | // static const UInt32 kFatSector = 0xFFFFFFFD; | 79 | static const UInt32 kFatSector = 0xfffffffd; |
| 57 | // static const UInt32 kMatSector = 0xFFFFFFFC; | 80 | static const UInt32 k_DIF_SECT = 0xfffffffc; // double-indirect file allocation table (DIFAT) |
| 58 | static const UInt32 kMaxValue = 0xFFFFFFFA; | 81 | static const UInt32 kMaxValue = 0xfffffffa; |
| 59 | } | 82 | } |
| 60 | 83 | ||
| 61 | namespace NItemType | 84 | namespace NItemType |
| 62 | { | 85 | { |
| 63 | static const Byte kEmpty = 0; | 86 | static const unsigned kEmpty = 0; |
| 64 | static const Byte kStorage = 1; | 87 | static const unsigned kStorage = 1; |
| 65 | // static const Byte kStream = 2; | 88 | static const unsigned kStream = 2; |
| 66 | // static const Byte kLockBytes = 3; | 89 | // static const unsigned kLockBytes = 3; |
| 67 | // static const Byte kProperty = 4; | 90 | // static const unsigned kProperty = 4; |
| 68 | static const Byte kRootStorage = 5; | 91 | static const unsigned kRootStorage = 5; |
| 92 | } | ||
| 93 | |||
| 94 | static const unsigned k_MiniSectorSizeBits = 6; | ||
| 95 | static const UInt32 k_LongStreamMinSize = 1 << 12; | ||
| 96 | |||
| 97 | static const unsigned k_Msi_NumBits = 6; | ||
| 98 | static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; | ||
| 99 | static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1; | ||
| 100 | static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1); | ||
| 101 | static const unsigned k_Msi_StartUnicodeChar = 0x3800; | ||
| 102 | static const unsigned k_Msi_SpecUnicodeChar = k_Msi_StartUnicodeChar + k_Msi_UnicodeRange; | ||
| 103 | // (k_Msi_SpecUnicodeChar == 0x4840) is used as special symbol that is used | ||
| 104 | // as first character in some names in dir entries | ||
| 105 | /* | ||
| 106 | static bool IsMsiName(const Byte *p) | ||
| 107 | { | ||
| 108 | unsigned c = Get16(p); | ||
| 109 | c -= k_Msi_StartUnicodeChar; | ||
| 110 | return c <= k_Msi_UnicodeRange; | ||
| 111 | } | ||
| 112 | */ | ||
| 113 | |||
| 114 | Z7_FORCE_INLINE static bool IsLargeStream(UInt64 size) | ||
| 115 | { | ||
| 116 | return size >= k_LongStreamMinSize; | ||
| 69 | } | 117 | } |
| 70 | 118 | ||
| 71 | static const unsigned kNameSizeMax = 64; | 119 | static const unsigned kNameSizeMax = 64; |
| 120 | static const UInt32 k_Item_Level_Unused = (UInt32)0 - 1; | ||
| 72 | 121 | ||
| 73 | struct CItem | 122 | struct CItem |
| 74 | { | 123 | { |
| 75 | Byte Name[kNameSizeMax]; | 124 | Byte Name[kNameSizeMax]; // must be aligned for 2-bytes |
| 76 | // UInt16 NameSize; | 125 | // UInt16 NameSize; |
| 77 | // UInt32 Flags; | 126 | // UInt32 Flags; |
| 78 | FILETIME CTime; | 127 | FILETIME CTime; |
| @@ -82,484 +131,792 @@ struct CItem | |||
| 82 | UInt32 RightDid; | 131 | UInt32 RightDid; |
| 83 | UInt32 SonDid; | 132 | UInt32 SonDid; |
| 84 | UInt32 Sid; | 133 | UInt32 Sid; |
| 85 | Byte Type; | 134 | unsigned Type; // Byte : we use unsigned instead of Byte for alignment |
| 135 | |||
| 136 | UInt32 Level; | ||
| 86 | 137 | ||
| 87 | bool IsEmpty() const { return Type == NItemType::kEmpty; } | 138 | bool IsEmptyType() const { return Type == NItemType::kEmpty; } |
| 88 | bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } | 139 | bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; } |
| 140 | bool IsStorage() const { return Type == NItemType::kStorage; } | ||
| 141 | |||
| 142 | bool IsLevel_Unused() const { return Level == k_Item_Level_Unused; } | ||
| 89 | 143 | ||
| 90 | void Parse(const Byte *p, bool mode64bit); | 144 | // bool IsSpecMsiName() const { return Get16(Name) == k_Msi_SpecUnicodeChar; } |
| 145 | bool AreMsiChars() const | ||
| 146 | { | ||
| 147 | for (unsigned i = 0; i < kNameSizeMax; i += 2) | ||
| 148 | { | ||
| 149 | unsigned c = Get16(Name + i); | ||
| 150 | if (c == 0) | ||
| 151 | break; | ||
| 152 | c -= k_Msi_StartUnicodeChar; | ||
| 153 | if (c <= k_Msi_UnicodeRange) | ||
| 154 | return true; | ||
| 155 | } | ||
| 156 | return false; | ||
| 157 | } | ||
| 158 | bool Parse(const Byte *p, bool mode64bit); | ||
| 91 | }; | 159 | }; |
| 92 | 160 | ||
| 161 | |||
| 162 | static const UInt32 k_Ref_Parent_Root = 0xffffffff; | ||
| 163 | |||
| 93 | struct CRef | 164 | struct CRef |
| 94 | { | 165 | { |
| 95 | int Parent; | 166 | UInt32 Parent; // index in Refs[] |
| 96 | UInt32 Did; | 167 | UInt32 Did; // index in Items[] |
| 97 | }; | 168 | }; |
| 98 | 169 | ||
| 170 | |||
| 99 | class CDatabase | 171 | class CDatabase |
| 100 | { | 172 | { |
| 101 | CObjArray<UInt32> MiniSids; | ||
| 102 | |||
| 103 | HRESULT AddNode(int parent, UInt32 did); | ||
| 104 | |||
| 105 | public: | 173 | public: |
| 174 | CRecordVector<CRef> Refs; | ||
| 175 | CObjectVector<CItem> Items; | ||
| 106 | CObjArray<UInt32> Fat; | 176 | CObjArray<UInt32> Fat; |
| 107 | CObjArray<UInt32> Mat; | 177 | CObjArray<UInt32> Mat; |
| 108 | CObjectVector<CItem> Items; | 178 | CObjArray<UInt32> MiniSids; |
| 109 | CRecordVector<CRef> Refs; | 179 | |
| 110 | private: | ||
| 111 | UInt32 NumSectorsInMiniStream; | ||
| 112 | public: | ||
| 113 | UInt32 MatSize; | ||
| 114 | UInt32 FatSize; | 180 | UInt32 FatSize; |
| 181 | UInt32 MatSize; | ||
| 182 | UInt32 NumSectors_in_MiniStream; | ||
| 115 | 183 | ||
| 116 | UInt32 LongStreamMinSize; | 184 | // UInt32 LongStreamMinSize; |
| 117 | unsigned SectorSizeBits; | 185 | unsigned SectorSizeBits; |
| 118 | unsigned MiniSectorSizeBits; | ||
| 119 | 186 | ||
| 120 | Int32 MainSubfile; | 187 | Int32 MainSubfile; |
| 121 | EType Type; | 188 | EArcType Type; |
| 189 | |||
| 190 | bool IsArc; | ||
| 191 | bool HeadersError; | ||
| 192 | // bool IsMsi; | ||
| 122 | 193 | ||
| 123 | UInt64 PhySize; | 194 | UInt64 PhySize; |
| 124 | UInt64 PhySize_Aligned; | 195 | UInt64 PhySize_Unaligned; |
| 196 | // UInt64 FreeSize; | ||
| 125 | 197 | ||
| 126 | bool IsNotArcType() const | 198 | IArchiveOpenCallback *OpenCallback; |
| 199 | UInt32 Callback_Cur; | ||
| 200 | |||
| 201 | private: | ||
| 202 | /* | ||
| 203 | HRESULT IncreaseOpenTotal(UInt32 numSects) | ||
| 127 | { | 204 | { |
| 128 | return | 205 | if (!OpenCallback) |
| 129 | Type != k_Type_Msi && | 206 | return S_OK; |
| 130 | Type != k_Type_Msp; | 207 | const UInt64 total = (UInt64)(Callback_Cur + numSects) << SectorSizeBits; |
| 208 | return OpenCallback->SetTotal(NULL, &total); | ||
| 131 | } | 209 | } |
| 210 | */ | ||
| 211 | HRESULT AddNodes(); | ||
| 212 | HRESULT ReadSector(IInStream *inStream, Byte *buf, UInt32 sid); | ||
| 213 | HRESULT ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest); | ||
| 214 | HRESULT Check_Item(unsigned index); | ||
| 132 | 215 | ||
| 133 | void UpdatePhySize(UInt64 val, UInt64 val_Aligned) | 216 | public: |
| 217 | bool IsNotArcType() const | ||
| 134 | { | 218 | { |
| 135 | if (PhySize < val) | 219 | return |
| 136 | PhySize = val; | 220 | Type != k_Type_Msi && |
| 137 | if (PhySize_Aligned < val_Aligned) | 221 | Type != k_Type_Msp && |
| 138 | PhySize_Aligned = val_Aligned; | 222 | Type != k_Type_Msm; |
| 139 | } | 223 | } |
| 140 | HRESULT ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid); | ||
| 141 | HRESULT ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest); | ||
| 142 | |||
| 143 | HRESULT Update_PhySize_WithItem(unsigned index); | ||
| 144 | 224 | ||
| 145 | void Clear(); | 225 | void Clear(); |
| 146 | bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; } | ||
| 147 | UString GetItemPath(UInt32 index) const; | 226 | UString GetItemPath(UInt32 index) const; |
| 148 | 227 | ||
| 149 | UInt64 GetItemPackSize(UInt64 size) const | 228 | UInt64 GetItemPackSize(UInt64 size) const |
| 150 | { | 229 | { |
| 151 | const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1; | 230 | const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : k_MiniSectorSizeBits)) - 1; |
| 152 | return (size + mask) & ~mask; | 231 | return (size + mask) & ~(UInt64)mask; |
| 153 | } | ||
| 154 | |||
| 155 | bool GetMiniCluster(UInt32 sid, UInt64 &res) const | ||
| 156 | { | ||
| 157 | const unsigned subBits = SectorSizeBits - MiniSectorSizeBits; | ||
| 158 | const UInt32 fid = sid >> subBits; | ||
| 159 | if (fid >= NumSectorsInMiniStream) | ||
| 160 | return false; | ||
| 161 | res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1)); | ||
| 162 | return true; | ||
| 163 | } | 232 | } |
| 164 | 233 | ||
| 165 | HRESULT Open(IInStream *inStream); | 234 | HRESULT Open(IInStream *inStream); |
| 166 | }; | 235 | }; |
| 167 | 236 | ||
| 168 | 237 | ||
| 169 | HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid) | 238 | HRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, UInt32 sid) |
| 170 | { | 239 | { |
| 171 | const UInt64 end = ((UInt64)sid + 2) << sectorSizeBits; | 240 | const unsigned sb = SectorSizeBits; |
| 172 | UpdatePhySize(end, end); | 241 | RINOK(InStream_SeekSet(inStream, ((UInt64)sid + 1) << sb)) |
| 173 | RINOK(InStream_SeekSet(inStream, (((UInt64)sid + 1) << sectorSizeBits))) | 242 | RINOK(ReadStream_FALSE(inStream, buf, (size_t)1 << sb)) |
| 174 | return ReadStream_FALSE(inStream, buf, (size_t)1 << sectorSizeBits); | 243 | if (OpenCallback) |
| 244 | { | ||
| 245 | if ((++Callback_Cur & 0xfff) == 0) | ||
| 246 | { | ||
| 247 | const UInt64 processed = (UInt64)Callback_Cur << sb; | ||
| 248 | const UInt64 numFiles = Items.Size(); | ||
| 249 | RINOK(OpenCallback->SetCompleted(&numFiles, &processed)) | ||
| 250 | } | ||
| 251 | } | ||
| 252 | return S_OK; | ||
| 175 | } | 253 | } |
| 176 | 254 | ||
| 177 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, unsigned sectorSizeBits, UInt32 sid, UInt32 *dest) | 255 | HRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest) |
| 178 | { | 256 | { |
| 179 | RINOK(ReadSector(inStream, buf, sectorSizeBits, sid)) | 257 | RINOK(ReadSector(inStream, buf, sid)) |
| 180 | const UInt32 sectorSize = (UInt32)1 << sectorSizeBits; | 258 | const size_t sectorSize = (size_t)1 << SectorSizeBits; |
| 181 | for (UInt32 t = 0; t < sectorSize; t += 4) | 259 | for (size_t t = 0; t < sectorSize; t += 4) |
| 182 | *dest++ = Get32(buf + t); | 260 | *dest++ = Get32(buf + t); |
| 183 | return S_OK; | 261 | return S_OK; |
| 184 | } | 262 | } |
| 185 | 263 | ||
| 264 | |||
| 265 | Z7_FORCE_INLINE | ||
| 186 | static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) | 266 | static void GetFileTimeFromMem(const Byte *p, FILETIME *ft) |
| 187 | { | 267 | { |
| 188 | ft->dwLowDateTime = Get32(p); | 268 | ft->dwLowDateTime = Get32(p); |
| 189 | ft->dwHighDateTime = Get32(p + 4); | 269 | ft->dwHighDateTime = Get32(p + 4); |
| 190 | } | 270 | } |
| 191 | 271 | ||
| 192 | void CItem::Parse(const Byte *p, bool mode64bit) | 272 | bool CItem::Parse(const Byte *p, bool mode64bit) |
| 193 | { | 273 | { |
| 194 | memcpy(Name, p, kNameSizeMax); | 274 | memcpy(Name, p, kNameSizeMax); |
| 195 | // NameSize = Get16(p + 64); | 275 | unsigned i; |
| 276 | for (i = 0; i < kNameSizeMax; i += 2) | ||
| 277 | if (*(const UInt16 *)(const void *)(p + i) == 0) | ||
| 278 | break; | ||
| 279 | #if 0 // 1 : for debug : for more strict field check | ||
| 280 | { | ||
| 281 | for (unsigned k = i; k < kNameSizeMax; k += 2) | ||
| 282 | if (*(const UInt16 *)(const void *)(p + k) != 0) | ||
| 283 | return false; | ||
| 284 | } | ||
| 285 | #endif | ||
| 196 | Type = p[66]; | 286 | Type = p[66]; |
| 287 | // DOC: names are limited to 32 UTF-16 code points, including the terminating null character. | ||
| 288 | if (!IsEmptyType()) | ||
| 289 | if (i == kNameSizeMax || i + 2 != Get16(p + 64)) // NameLength | ||
| 290 | return false; | ||
| 291 | if (p[67] >= 2) // Color: 0 (red) or 1 (black) | ||
| 292 | return false; | ||
| 197 | LeftDid = Get32(p + 68); | 293 | LeftDid = Get32(p + 68); |
| 198 | RightDid = Get32(p + 72); | 294 | RightDid = Get32(p + 72); |
| 199 | SonDid = Get32(p + 76); | 295 | SonDid = Get32(p + 76); |
| 200 | // Flags = Get32(p + 96); | 296 | // if (Get32(p + 96) == 0) return false; // State / Flags |
| 201 | GetFileTimeFromMem(p + 100, &CTime); | 297 | GetFileTimeFromMem(p + 100, &CTime); |
| 202 | GetFileTimeFromMem(p + 108, &MTime); | 298 | GetFileTimeFromMem(p + 108, &MTime); |
| 203 | Sid = Get32(p + 116); | 299 | Sid = Get32(p + 116); |
| 204 | Size = Get32(p + 120); | 300 | Size = Get32(p + 120); |
| 301 | /* MS DOC: it is recommended that parsers ignore the most | ||
| 302 | significant 32 bits of this field in version 3 compound files */ | ||
| 205 | if (mode64bit) | 303 | if (mode64bit) |
| 206 | Size |= ((UInt64)Get32(p + 124) << 32); | 304 | Size |= ((UInt64)Get32(p + 124) << 32); |
| 305 | return true; | ||
| 207 | } | 306 | } |
| 208 | 307 | ||
| 308 | |||
| 209 | void CDatabase::Clear() | 309 | void CDatabase::Clear() |
| 210 | { | 310 | { |
| 311 | Type = k_Type_Common; | ||
| 312 | MainSubfile = -1; | ||
| 313 | IsArc = false; | ||
| 314 | HeadersError = false; | ||
| 315 | // IsMsi = false; | ||
| 211 | PhySize = 0; | 316 | PhySize = 0; |
| 212 | PhySize_Aligned = 0; | 317 | PhySize_Unaligned = 0; |
| 213 | 318 | // FreeSize = 0; | |
| 319 | Callback_Cur = 0; | ||
| 320 | // OpenCallback = NULL; | ||
| 321 | |||
| 322 | FatSize = 0; | ||
| 323 | MatSize = 0; | ||
| 324 | NumSectors_in_MiniStream = 0; | ||
| 325 | |||
| 214 | Fat.Free(); | 326 | Fat.Free(); |
| 215 | MiniSids.Free(); | ||
| 216 | Mat.Free(); | 327 | Mat.Free(); |
| 328 | MiniSids.Free(); | ||
| 217 | Items.Clear(); | 329 | Items.Clear(); |
| 218 | Refs.Clear(); | 330 | Refs.Clear(); |
| 219 | } | 331 | } |
| 220 | 332 | ||
| 221 | static const UInt32 kNoDid = 0xFFFFFFFF; | ||
| 222 | 333 | ||
| 223 | HRESULT CDatabase::AddNode(int parent, UInt32 did) | 334 | static const UInt32 kNoDid = 0xffffffff; |
| 335 | |||
| 336 | HRESULT CDatabase::AddNodes() | ||
| 224 | { | 337 | { |
| 225 | if (did == kNoDid) | 338 | UInt32 index = Items[0].SonDid; // Items[0] is root item |
| 339 | if (index == kNoDid) // no files case | ||
| 226 | return S_OK; | 340 | return S_OK; |
| 227 | if (did >= (UInt32)Items.Size()) | 341 | if (index == 0 || index >= Items.Size()) |
| 228 | return S_FALSE; | ||
| 229 | const CItem &item = Items[did]; | ||
| 230 | if (item.IsEmpty()) | ||
| 231 | return S_FALSE; | ||
| 232 | CRef ref; | ||
| 233 | ref.Parent = parent; | ||
| 234 | ref.Did = did; | ||
| 235 | const unsigned index = Refs.Add(ref); | ||
| 236 | if (Refs.Size() > Items.Size()) | ||
| 237 | return S_FALSE; | 342 | return S_FALSE; |
| 238 | RINOK(AddNode(parent, item.LeftDid)) | 343 | |
| 239 | RINOK(AddNode(parent, item.RightDid)) | 344 | CObjArray<UInt32> itemParents(Items.Size()); |
| 240 | if (item.IsDir()) | 345 | CByteArr states(Items.Size()); |
| 346 | memset(itemParents, 0, (size_t)Items.Size() * sizeof(itemParents[0])); // optional | ||
| 347 | memset(states, 0, Items.Size()); | ||
| 348 | |||
| 349 | #if 1 // 0 : for debug | ||
| 350 | const UInt32 k_exitParent = 0; | ||
| 351 | const UInt32 k_startLevel = 1; | ||
| 352 | // we don't show "Root Entry" dir | ||
| 353 | states[0] = 3; // we mark root node as processed, also we block any cycle links to root node | ||
| 354 | // itemParents[0] = 0xffffffff; // optional / unused value | ||
| 355 | #else | ||
| 356 | // we show item[0] "Root Entry" dir | ||
| 357 | const UInt32 k_exitParent = 0xffffffff; | ||
| 358 | const UInt32 k_startLevel = 0; | ||
| 359 | index = 0; | ||
| 360 | #endif | ||
| 361 | |||
| 362 | UInt32 level = k_startLevel; // directory level | ||
| 363 | unsigned state = 0; | ||
| 364 | UInt32 parent = k_exitParent; // in Items[], itemParents[], states[] | ||
| 365 | UInt32 refParent = k_Ref_Parent_Root; // in Refs[] | ||
| 366 | |||
| 367 | for (;;) | ||
| 241 | { | 368 | { |
| 242 | RINOK(AddNode((int)index, item.SonDid)) | 369 | if (state >= 3) |
| 243 | } | 370 | { |
| 244 | return S_OK; | 371 | // we return to parent node |
| 245 | } | 372 | if (state != 3) |
| 373 | return E_FAIL; | ||
| 374 | index = parent; | ||
| 375 | if (index == k_exitParent) | ||
| 376 | break; | ||
| 377 | if (index >= Items.Size()) | ||
| 378 | return E_FAIL; // (index) was checked already | ||
| 379 | parent = itemParents[index]; | ||
| 380 | state = states[index]; | ||
| 381 | if (state == 0) | ||
| 382 | return E_FAIL; | ||
| 383 | if (state == 2) | ||
| 384 | { | ||
| 385 | // we return to parent Dir node | ||
| 386 | if (refParent >= Refs.Size()) | ||
| 387 | return E_FAIL; | ||
| 388 | refParent = Refs[refParent].Parent; | ||
| 389 | level--; | ||
| 390 | } | ||
| 391 | continue; | ||
| 392 | } | ||
| 246 | 393 | ||
| 247 | static UString CompoundNameToFileName(const UString &s) | 394 | if (index >= Items.Size()) |
| 248 | { | 395 | return S_FALSE; |
| 249 | UString res; | 396 | CItem &item = Items[index]; |
| 250 | for (unsigned i = 0; i < s.Len(); i++) | 397 | if (item.IsEmptyType()) |
| 398 | return S_FALSE; | ||
| 399 | item.Level = level; | ||
| 400 | state++; | ||
| 401 | states[index] = (Byte)state; // we mark current (index) node as used node | ||
| 402 | |||
| 403 | UInt32 newIndex; | ||
| 404 | if (state != 2) | ||
| 405 | newIndex = (state < 2) ? item.LeftDid : item.RightDid; | ||
| 406 | else | ||
| 407 | { | ||
| 408 | CRef ref; | ||
| 409 | ref.Parent = refParent; | ||
| 410 | ref.Did = index; | ||
| 411 | const unsigned refIndex = Refs.Add(ref); | ||
| 412 | if (!item.IsDir()) | ||
| 413 | continue; | ||
| 414 | newIndex = item.SonDid; | ||
| 415 | if (newIndex != kNoDid) | ||
| 416 | { | ||
| 417 | level++; | ||
| 418 | refParent = refIndex; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | if (newIndex != kNoDid) | ||
| 423 | { | ||
| 424 | itemParents[index] = parent; | ||
| 425 | state = 0; | ||
| 426 | parent = index; | ||
| 427 | index = newIndex; | ||
| 428 | if (index >= Items.Size() || states[index]) | ||
| 429 | return S_FALSE; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | if (level != k_startLevel || refParent != k_Ref_Parent_Root) | ||
| 434 | return E_FAIL; | ||
| 435 | #if 1 // 1 : optional | ||
| 436 | // we check that all non-empty items were processed correctly | ||
| 437 | FOR_VECTOR(i, Items) | ||
| 251 | { | 438 | { |
| 252 | const wchar_t c = s[i]; | 439 | const unsigned st = states[i]; |
| 253 | if ((unsigned)(int)c < 0x20) | 440 | if (Items[i].IsEmptyType()) |
| 254 | { | 441 | { |
| 255 | res.Add_Char('['); | 442 | if (st) |
| 256 | res.Add_UInt32((UInt32)(unsigned)(int)c); | 443 | return E_FAIL; |
| 257 | res.Add_Char(']'); | ||
| 258 | } | 444 | } |
| 445 | else if (st == 3) | ||
| 446 | continue; | ||
| 447 | else if (st) | ||
| 448 | return E_FAIL; | ||
| 259 | else | 449 | else |
| 260 | res += c; | 450 | return S_FALSE; // there is unused directory item |
| 261 | } | 451 | } |
| 262 | return res; | 452 | #endif |
| 453 | return S_OK; | ||
| 263 | } | 454 | } |
| 264 | 455 | ||
| 456 | |||
| 265 | static const char k_Msi_Chars[] = | 457 | static const char k_Msi_Chars[] = |
| 266 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; | 458 | "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._"; |
| 267 | 459 | static const char k_Msi_SpecChar_Replace = '!'; | |
| 268 | // static const char * const k_Msi_ID = ""; // "{msi}"; | ||
| 269 | static const char k_Msi_SpecChar = '!'; | ||
| 270 | |||
| 271 | static const unsigned k_Msi_NumBits = 6; | ||
| 272 | static const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits; | ||
| 273 | static const unsigned k_Msi_CharMask = k_Msi_NumChars - 1; | ||
| 274 | static const unsigned k_Msi_StartUnicodeChar = 0x3800; | ||
| 275 | static const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1); | ||
| 276 | |||
| 277 | |||
| 278 | static bool IsMsiName(const Byte *p) | ||
| 279 | { | ||
| 280 | UInt32 c = Get16(p); | ||
| 281 | return | ||
| 282 | c >= k_Msi_StartUnicodeChar && | ||
| 283 | c <= k_Msi_StartUnicodeChar + k_Msi_UnicodeRange; | ||
| 284 | } | ||
| 285 | 460 | ||
| 286 | static bool AreEqualNames(const Byte *rawName, const char *asciiName) | 461 | static bool AreEqualNames(const Byte *rawName, const char *asciiName) |
| 287 | { | 462 | { |
| 288 | for (unsigned i = 0; i < kNameSizeMax / 2; i++) | 463 | for (;;) |
| 289 | { | 464 | { |
| 290 | wchar_t c = Get16(rawName + i * 2); | 465 | const unsigned c = Get16(rawName); |
| 291 | wchar_t c2 = (Byte)asciiName[i]; | 466 | rawName += 2; |
| 467 | const unsigned c2 = (Byte)*asciiName; | ||
| 468 | asciiName++; | ||
| 292 | if (c != c2) | 469 | if (c != c2) |
| 293 | return false; | 470 | return false; |
| 294 | if (c == 0) | 471 | if (c2 == 0) |
| 295 | return true; | 472 | return true; |
| 296 | } | 473 | } |
| 297 | return false; | ||
| 298 | } | 474 | } |
| 299 | 475 | ||
| 300 | static bool CompoundMsiNameToFileName(const UString &name, UString &res) | ||
| 301 | { | ||
| 302 | res.Empty(); | ||
| 303 | for (unsigned i = 0; i < name.Len(); i++) | ||
| 304 | { | ||
| 305 | wchar_t c = name[i]; | ||
| 306 | if (c < (wchar_t)k_Msi_StartUnicodeChar || c > (wchar_t)(k_Msi_StartUnicodeChar + k_Msi_UnicodeRange)) | ||
| 307 | return false; | ||
| 308 | /* | ||
| 309 | if (i == 0) | ||
| 310 | res += k_Msi_ID; | ||
| 311 | */ | ||
| 312 | c -= (wchar_t)k_Msi_StartUnicodeChar; | ||
| 313 | |||
| 314 | const unsigned c0 = (unsigned)c & k_Msi_CharMask; | ||
| 315 | const unsigned c1 = (unsigned)c >> k_Msi_NumBits; | ||
| 316 | 476 | ||
| 317 | if (c1 <= k_Msi_NumChars) | 477 | static void MsiName_To_FileName(const Byte *p, UString &res) |
| 318 | { | ||
| 319 | res.Add_Char(k_Msi_Chars[c0]); | ||
| 320 | if (c1 == k_Msi_NumChars) | ||
| 321 | break; | ||
| 322 | res.Add_Char(k_Msi_Chars[c1]); | ||
| 323 | } | ||
| 324 | else | ||
| 325 | res.Add_Char(k_Msi_SpecChar); | ||
| 326 | } | ||
| 327 | return true; | ||
| 328 | } | ||
| 329 | |||
| 330 | static UString ConvertName(const Byte *p, bool &isMsi) | ||
| 331 | { | 478 | { |
| 332 | isMsi = false; | 479 | res.Empty(); |
| 333 | UString s; | ||
| 334 | |||
| 335 | for (unsigned i = 0; i < kNameSizeMax; i += 2) | 480 | for (unsigned i = 0; i < kNameSizeMax; i += 2) |
| 336 | { | 481 | { |
| 337 | wchar_t c = Get16(p + i); | 482 | unsigned c = Get16(p + i); |
| 338 | if (c == 0) | 483 | if (c == 0) |
| 339 | break; | 484 | break; |
| 340 | s += c; | 485 | if (c <= k_Msi_SpecUnicodeChar) |
| 341 | } | 486 | { |
| 342 | 487 | if (c < k_Msi_StartUnicodeChar) | |
| 343 | UString msiName; | 488 | { |
| 344 | if (CompoundMsiNameToFileName(s, msiName)) | 489 | if (c < 0x20) |
| 345 | { | 490 | { |
| 346 | isMsi = true; | 491 | res.Add_Char('['); |
| 347 | return msiName; | 492 | res.Add_UInt32((UInt32)c); |
| 493 | c = ']'; | ||
| 494 | } | ||
| 495 | } | ||
| 496 | else | ||
| 497 | { | ||
| 498 | #if 0 // 1 : for debug | ||
| 499 | if (i == 0) res += "{msi}"; | ||
| 500 | #endif | ||
| 501 | c -= k_Msi_StartUnicodeChar; | ||
| 502 | const unsigned c1 = (unsigned)c >> k_Msi_NumBits; | ||
| 503 | if (c1 <= k_Msi_NumChars) | ||
| 504 | { | ||
| 505 | res.Add_Char(k_Msi_Chars[(unsigned)c & k_Msi_CharMask]); | ||
| 506 | if (c1 == k_Msi_NumChars) | ||
| 507 | continue; | ||
| 508 | c = (Byte)k_Msi_Chars[c1]; | ||
| 509 | } | ||
| 510 | else | ||
| 511 | c = k_Msi_SpecChar_Replace; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | res += (wchar_t)c; | ||
| 348 | } | 515 | } |
| 349 | return CompoundNameToFileName(s); | ||
| 350 | } | 516 | } |
| 351 | 517 | ||
| 352 | static UString ConvertName(const Byte *p) | ||
| 353 | { | ||
| 354 | bool isMsi; | ||
| 355 | return ConvertName(p, isMsi); | ||
| 356 | } | ||
| 357 | 518 | ||
| 358 | UString CDatabase::GetItemPath(UInt32 index) const | 519 | UString CDatabase::GetItemPath(UInt32 index) const |
| 359 | { | 520 | { |
| 360 | UString s; | 521 | UString s; |
| 361 | while (index != kNoDid) | 522 | UString name; |
| 523 | unsigned level = 0; | ||
| 524 | while (index != k_Ref_Parent_Root) | ||
| 362 | { | 525 | { |
| 363 | const CRef &ref = Refs[index]; | 526 | const CRef &ref = Refs[index]; |
| 364 | const CItem &item = Items[ref.Did]; | 527 | const CItem &item = Items[ref.Did]; |
| 365 | if (!s.IsEmpty()) | 528 | if (!s.IsEmpty()) |
| 366 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); | 529 | s.InsertAtFront(WCHAR_PATH_SEPARATOR); |
| 367 | s.Insert(0, ConvertName(item.Name)); | 530 | // if (IsMsi) |
| 368 | index = (unsigned)ref.Parent; | 531 | MsiName_To_FileName(item.Name, name); |
| 532 | // else NonMsiName_To_FileName(item.Name, name); | ||
| 533 | NItemName::NormalizeSlashes_in_FileName_for_OsPath(name); | ||
| 534 | if (name.IsEmpty()) | ||
| 535 | name = "[]"; | ||
| 536 | s.Insert(0, name); | ||
| 537 | index = ref.Parent; | ||
| 538 | #ifdef Z7_COMPOUND_SHOW_DELETED | ||
| 539 | if (item.IsLevel_Unused()) | ||
| 540 | { | ||
| 541 | s.Insert(0, L"[DELETED]" WSTRING_PATH_SEPARATOR); | ||
| 542 | break; | ||
| 543 | } | ||
| 544 | #endif | ||
| 545 | if (item.Level >= k_Long_path_level_limit && level) | ||
| 546 | { | ||
| 547 | s.Insert(0, L"[LONG_PATH]" WSTRING_PATH_SEPARATOR); | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | level = 1; // level++; | ||
| 369 | } | 551 | } |
| 370 | return s; | 552 | return s; |
| 371 | } | 553 | } |
| 372 | 554 | ||
| 373 | HRESULT CDatabase::Update_PhySize_WithItem(unsigned index) | 555 | |
| 556 | HRESULT CDatabase::Check_Item(unsigned index) | ||
| 374 | { | 557 | { |
| 375 | const CItem &item = Items[index]; | 558 | const CItem &item = Items[index]; |
| 376 | const bool isLargeStream = (index == 0 || IsLargeStream(item.Size)); | 559 | if (item.IsEmptyType() || item.IsStorage()) |
| 377 | if (!isLargeStream) | ||
| 378 | return S_OK; | 560 | return S_OK; |
| 379 | const unsigned bsLog = isLargeStream ? SectorSizeBits : MiniSectorSizeBits; | ||
| 380 | // streamSpec->Size = item.Size; | ||
| 381 | |||
| 382 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 383 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; | ||
| 384 | if (numClusters64 >= ((UInt32)1 << 31)) | ||
| 385 | return S_FALSE; | ||
| 386 | UInt32 sid = item.Sid; | ||
| 387 | UInt64 size = item.Size; | 561 | UInt64 size = item.Size; |
| 388 | 562 | const bool isLargeStream = (index == 0 || IsLargeStream(size)); | |
| 389 | if (size != 0) | 563 | if (!isLargeStream) |
| 390 | { | 564 | { |
| 391 | for (;; size -= clusterSize) | 565 | const unsigned bsLog = k_MiniSectorSizeBits; |
| 566 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 567 | const UInt64 numClusters = (size + clusterSize - 1) >> bsLog; | ||
| 568 | if (numClusters > MatSize) | ||
| 569 | return S_FALSE; | ||
| 570 | UInt32 sid = item.Sid; | ||
| 571 | if (size != 0) | ||
| 392 | { | 572 | { |
| 393 | // if (isLargeStream) | 573 | for (;; size -= clusterSize) |
| 574 | { | ||
| 575 | if (sid >= MatSize) | ||
| 576 | return S_FALSE; | ||
| 577 | const unsigned subBits = SectorSizeBits - k_MiniSectorSizeBits; | ||
| 578 | const UInt32 fid = sid >> subBits; | ||
| 579 | if (fid >= NumSectors_in_MiniStream) | ||
| 580 | return false; | ||
| 581 | sid = Mat[sid]; | ||
| 582 | if (size <= clusterSize) | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | if (sid != NFatID::kEndOfChain) | ||
| 587 | return S_FALSE; | ||
| 588 | } | ||
| 589 | else | ||
| 590 | { | ||
| 591 | const unsigned bsLog = SectorSizeBits; | ||
| 592 | const UInt32 clusterSize = (UInt32)1 << bsLog; | ||
| 593 | const UInt64 numClusters = (size + clusterSize - 1) >> bsLog; | ||
| 594 | if (numClusters > FatSize) | ||
| 595 | return S_FALSE; | ||
| 596 | UInt32 sid = item.Sid; | ||
| 597 | if (size != 0) | ||
| 598 | { | ||
| 599 | for (;; size -= clusterSize) | ||
| 394 | { | 600 | { |
| 395 | if (sid >= FatSize) | 601 | if (sid >= FatSize) |
| 396 | return S_FALSE; | 602 | return S_FALSE; |
| 397 | UInt64 end = ((UInt64)sid + 1) << bsLog; | 603 | const UInt32 sidPrev = sid; |
| 398 | const UInt64 end_Aligned = end + clusterSize; | ||
| 399 | if (size < clusterSize) | ||
| 400 | end += size; | ||
| 401 | else | ||
| 402 | end = end_Aligned; | ||
| 403 | UpdatePhySize(end, end_Aligned); | ||
| 404 | sid = Fat[sid]; | 604 | sid = Fat[sid]; |
| 605 | if (size <= clusterSize) | ||
| 606 | { | ||
| 607 | const UInt64 phySize = (((UInt64)sidPrev + 1) << SectorSizeBits) + size; | ||
| 608 | if (PhySize_Unaligned < phySize) | ||
| 609 | PhySize_Unaligned = phySize; | ||
| 610 | break; | ||
| 611 | } | ||
| 405 | } | 612 | } |
| 406 | if (size <= clusterSize) | ||
| 407 | break; | ||
| 408 | } | 613 | } |
| 614 | if (sid != NFatID::kEndOfChain) | ||
| 615 | return S_FALSE; | ||
| 409 | } | 616 | } |
| 410 | if (sid != NFatID::kEndOfChain) | ||
| 411 | return S_FALSE; | ||
| 412 | return S_OK; | 617 | return S_OK; |
| 413 | } | 618 | } |
| 414 | 619 | ||
| 415 | // There is name "[!]MsiPatchSequence" in msp files | ||
| 416 | static const unsigned kMspSequence_Size = 18; | ||
| 417 | static const Byte kMspSequence[kMspSequence_Size] = | ||
| 418 | { 0x40, 0x48, 0x96, 0x45, 0x6C, 0x3E, 0xE4, 0x45, | ||
| 419 | 0xE6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41, | ||
| 420 | 0x37, 0x41 }; | ||
| 421 | 620 | ||
| 422 | HRESULT CDatabase::Open(IInStream *inStream) | 621 | HRESULT CDatabase::Open(IInStream *inStream) |
| 423 | { | 622 | { |
| 424 | MainSubfile = -1; | 623 | const unsigned kHeaderSize = 512; |
| 425 | Type = k_Type_Common; | 624 | UInt32 p32[kHeaderSize / 4]; |
| 426 | const UInt32 kHeaderSize = 512; | 625 | RINOK(ReadStream_FALSE(inStream, p32, kHeaderSize)) |
| 427 | Byte p[kHeaderSize]; | 626 | const Byte *p = (const Byte *)(const void *)p32; |
| 428 | PhySize = kHeaderSize; | 627 | if (memcmp(p, kSignature, Z7_ARRAY_SIZE(kSignature))) |
| 429 | RINOK(ReadStream_FALSE(inStream, p, kHeaderSize)) | 628 | return S_FALSE; |
| 430 | if (memcmp(p, kSignature, Z7_ARRAY_SIZE(kSignature)) != 0) | 629 | /* |
| 630 | if (memcmp(p + 8, k_CLSID_AAF_V3, Z7_ARRAY_SIZE(k_CLSID_AAF_V3)) == 0 || | ||
| 631 | memcmp(p + 8, k_CLSID_AAF_V4, Z7_ARRAY_SIZE(k_CLSID_AAF_V4)) == 0) | ||
| 632 | */ | ||
| 633 | if (Get32(p32 + 4) == 0x342b0e06) // simplified AAF signature check | ||
| 634 | Type = k_Type_Aaf; | ||
| 635 | if (Get16(p + 0x18) != 0x3e) // minorVer | ||
| 431 | return S_FALSE; | 636 | return S_FALSE; |
| 432 | if (Get16(p + 0x1A) > 4) // majorVer | 637 | const unsigned ver = Get16(p + 0x1a); // majorVer |
| 638 | if (ver < 3 || ver > 4) | ||
| 433 | return S_FALSE; | 639 | return S_FALSE; |
| 434 | if (Get16(p + 0x1C) != 0xFFFE) // Little-endian | 640 | if (Get16(p + 0x1c) != 0xfffe) // Little-endian |
| 641 | return S_FALSE; | ||
| 642 | const unsigned sectorSizeBits = Get16(p + 0x1e); | ||
| 643 | if (sectorSizeBits != ver * 3) // (ver == 3 ? 9 : 12) | ||
| 435 | return S_FALSE; | 644 | return S_FALSE; |
| 436 | unsigned sectorSizeBits = Get16(p + 0x1E); | ||
| 437 | bool mode64bit = (sectorSizeBits >= 12); | ||
| 438 | unsigned miniSectorSizeBits = Get16(p + 0x20); | ||
| 439 | SectorSizeBits = sectorSizeBits; | 645 | SectorSizeBits = sectorSizeBits; |
| 440 | MiniSectorSizeBits = miniSectorSizeBits; | 646 | if (Get16(p + 0x20) != k_MiniSectorSizeBits) |
| 647 | return S_FALSE; | ||
| 648 | |||
| 649 | IsArc = true; | ||
| 650 | HeadersError = true; | ||
| 441 | 651 | ||
| 442 | if (sectorSizeBits > 24 || | 652 | const bool mode64bit = (sectorSizeBits >= 12); // (ver == 4) |
| 443 | sectorSizeBits < 7 || | 653 | if (Get16(p + 0x22) || p32[9]) // reserved |
| 444 | miniSectorSizeBits > 24 || | 654 | return S_FALSE; |
| 445 | miniSectorSizeBits < 2 || | 655 | |
| 446 | miniSectorSizeBits > sectorSizeBits) | 656 | const UInt32 numDirSectors = Get32(p32 + 10); |
| 657 | // If (ver==3), the Number of Directory Sectors MUST be zero. | ||
| 658 | if (ver != 3 + (unsigned)(numDirSectors != 0)) | ||
| 659 | return S_FALSE; | ||
| 660 | if (numDirSectors > ((1u << (32 - 2)) >> (sectorSizeBits - (7 + 2)))) | ||
| 661 | return S_FALSE; | ||
| 662 | |||
| 663 | const UInt32 numSectorsForFAT = Get32(p32 + 11); // SAT | ||
| 664 | |||
| 665 | // MSDOC: A 512-byte sector compound file MUST be no greater than 2 GB in size for compatibility reasons. | ||
| 666 | // but actual restriction for windows compond creation code can be more strict: | ||
| 667 | // (numSectorsForFAT < (1 << 15)) : actual restriction in win10 for compound creation code | ||
| 668 | // (numSectorsForFAT <= (1 << 15)) : relaxed restriction to allow 2 GB files. | ||
| 669 | if (sectorSizeBits == 9 && | ||
| 670 | numSectorsForFAT >= (1u << (31 - (9 + 9 - 2)))) // we use most strict check | ||
| 447 | return S_FALSE; | 671 | return S_FALSE; |
| 448 | UInt32 numSectorsForFAT = Get32(p + 0x2C); // SAT | ||
| 449 | LongStreamMinSize = Get32(p + 0x38); | ||
| 450 | |||
| 451 | UInt32 sectSize = (UInt32)1 << sectorSizeBits; | ||
| 452 | 672 | ||
| 453 | CByteBuffer sect(sectSize); | 673 | // const UInt32 TransactionSignatureNumber = Get32(p32 + 13); |
| 674 | if (Get32(p32 + 14) != k_LongStreamMinSize) | ||
| 675 | return S_FALSE; | ||
| 454 | 676 | ||
| 455 | unsigned ssb2 = sectorSizeBits - 2; | 677 | const unsigned ssb2 = sectorSizeBits - 2; |
| 456 | UInt32 numSidsInSec = (UInt32)1 << ssb2; | 678 | const UInt32 numSidsInSec = (UInt32)1 << ssb2; |
| 457 | UInt32 numFatItems = numSectorsForFAT << ssb2; | 679 | const UInt32 numFatItems = numSectorsForFAT << ssb2; |
| 458 | if ((numFatItems >> ssb2) != numSectorsForFAT) | 680 | if (numFatItems == 0 || (numFatItems >> ssb2) != numSectorsForFAT) |
| 459 | return S_FALSE; | 681 | return S_FALSE; |
| 460 | FatSize = numFatItems; | ||
| 461 | 682 | ||
| 683 | const size_t sectSize = (size_t)1 << sectorSizeBits; | ||
| 684 | CByteArr sect(sectSize); | ||
| 685 | CByteArr used(numFatItems); | ||
| 686 | // don't change these const values. These values use same order as (0xffffffff - NFatID::const) | ||
| 687 | // const Byte k_Used_Free = 0; | ||
| 688 | const Byte k_Used_ChainTo = 1; | ||
| 689 | const Byte k_Used_FAT = 2; | ||
| 690 | const Byte k_Used_DIFAT = 3; | ||
| 691 | memset(used, 0, numFatItems); | ||
| 692 | UInt32 *fat; | ||
| 462 | { | 693 | { |
| 463 | UInt32 numSectorsForBat = Get32(p + 0x48); // master sector allocation table | 694 | // ========== READ FAT ========== |
| 464 | const UInt32 kNumHeaderBatItems = 109; | 695 | const UInt32 numSectorsForBat = Get32(p32 + 18); // master sector allocation table |
| 465 | UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); | 696 | const unsigned ssb2_m1 = ssb2 - 1; |
| 466 | if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat) | 697 | if (numSectorsForBat > ((1u << 30) >> ssb2_m1 >> ssb2_m1)) |
| 467 | return S_FALSE; | 698 | return S_FALSE; |
| 699 | const unsigned kNumHeaderBatItems = 109; | ||
| 700 | UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); // real size can be smaller | ||
| 468 | CObjArray<UInt32> bat(numBatItems); | 701 | CObjArray<UInt32> bat(numBatItems); |
| 469 | UInt32 i; | 702 | size_t i; |
| 470 | for (i = 0; i < kNumHeaderBatItems; i++) | 703 | for (i = 0; i < kNumHeaderBatItems; i++) |
| 471 | bat[i] = Get32(p + 0x4c + i * 4); | 704 | bat[i] = Get32(p32 + 19 + i); |
| 472 | UInt32 sid = Get32(p + 0x44); | ||
| 473 | for (UInt32 s = 0; s < numSectorsForBat; s++) | ||
| 474 | { | 705 | { |
| 475 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i)) | 706 | UInt32 sid = Get32(p32 + 17); |
| 476 | i += numSidsInSec - 1; | 707 | for (UInt32 s = 0; s < numSectorsForBat; s++) |
| 477 | sid = bat[i]; | 708 | { |
| 709 | if (sid >= numFatItems || used[sid]) | ||
| 710 | return S_FALSE; | ||
| 711 | used[sid] = k_Used_DIFAT; | ||
| 712 | RINOK(ReadIDs(inStream, sect, sid, bat + i)) | ||
| 713 | i += numSidsInSec - 1; | ||
| 714 | sid = bat[i]; | ||
| 715 | } | ||
| 716 | if (sid != NFatID::kEndOfChain // NFatID::kEndOfChain is expected value for most files | ||
| 717 | && sid != NFatID::kFree) // NFatID::kFree is used in some AAF files | ||
| 718 | return S_FALSE; | ||
| 478 | } | 719 | } |
| 479 | numBatItems = i; | 720 | numBatItems = (UInt32)i; // corrected value |
| 480 | 721 | if (numSectorsForFAT > numBatItems) | |
| 722 | return S_FALSE; | ||
| 723 | for (i = numSectorsForFAT; i < numBatItems; i++) | ||
| 724 | if (bat[i] != NFatID::kFree) | ||
| 725 | return S_FALSE; | ||
| 726 | |||
| 727 | // RINOK(IncreaseOpenTotal(numSectorsForFAT + numDirSectors)) | ||
| 728 | |||
| 481 | Fat.Alloc(numFatItems); | 729 | Fat.Alloc(numFatItems); |
| 482 | UInt32 j = 0; | 730 | fat = Fat; |
| 483 | 731 | for (i = 0; i < numSectorsForFAT; i++) | |
| 484 | for (i = 0; i < numFatItems; j++, i += numSidsInSec) | ||
| 485 | { | 732 | { |
| 486 | if (j >= numBatItems) | 733 | const UInt32 sectorIndex = bat[i]; |
| 734 | if (sectorIndex >= numFatItems) | ||
| 487 | return S_FALSE; | 735 | return S_FALSE; |
| 488 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i)) | 736 | if (used[sectorIndex]) |
| 737 | return S_FALSE; | ||
| 738 | used[sectorIndex] = k_Used_FAT; | ||
| 739 | UInt32 *fat2 = fat + ((size_t)i << ssb2); | ||
| 740 | RINOK(ReadIDs(inStream, sect, sectorIndex, fat2)) | ||
| 741 | for (size_t k = 0; k < numSidsInSec; k++) | ||
| 742 | { | ||
| 743 | const UInt32 sid = fat2[k]; | ||
| 744 | if (sid > NFatID::kMaxValue) | ||
| 745 | { | ||
| 746 | if (sid == NFatID::k_DIF_SECT | ||
| 747 | && used[((size_t)i << ssb2) + k] != k_Used_DIFAT) | ||
| 748 | return S_FALSE; | ||
| 749 | continue; | ||
| 750 | } | ||
| 751 | if (sid >= numFatItems || used[sid]) | ||
| 752 | return S_FALSE; // strict error check | ||
| 753 | used[sid] = k_Used_ChainTo; | ||
| 754 | } | ||
| 489 | } | 755 | } |
| 490 | FatSize = numFatItems = i; | 756 | { |
| 757 | for (i = 0; i < numSectorsForFAT; i++) | ||
| 758 | if (fat[bat[i]] != NFatID::kFatSector) | ||
| 759 | return S_FALSE; | ||
| 760 | } | ||
| 761 | FatSize = numFatItems; | ||
| 762 | } | ||
| 763 | |||
| 764 | { | ||
| 765 | size_t i = numFatItems; | ||
| 766 | do | ||
| 767 | if (fat[i - 1] != NFatID::kFree) | ||
| 768 | break; | ||
| 769 | while (--i); | ||
| 770 | PhySize = ((UInt64)i + 1) << sectorSizeBits; | ||
| 771 | /* | ||
| 772 | if (i) | ||
| 773 | { | ||
| 774 | const UInt32 *lim = fat + i; | ||
| 775 | UInt32 num = 0; | ||
| 776 | do | ||
| 777 | if (*fat++ == NFatID::kFree) | ||
| 778 | num++; | ||
| 779 | while (fat != lim); | ||
| 780 | FreeSize = num << sectorSizeBits; | ||
| 781 | } | ||
| 782 | */ | ||
| 491 | } | 783 | } |
| 492 | 784 | ||
| 493 | UInt32 numMatItems; | 785 | UInt32 numMatItems; |
| 494 | { | 786 | { |
| 495 | UInt32 numSectorsForMat = Get32(p + 0x40); | 787 | // ========== READ MAT ========== |
| 788 | const UInt32 numSectorsForMat = Get32(p32 + 16); | ||
| 496 | numMatItems = (UInt32)numSectorsForMat << ssb2; | 789 | numMatItems = (UInt32)numSectorsForMat << ssb2; |
| 497 | if ((numMatItems >> ssb2) != numSectorsForMat) | 790 | if ((numMatItems >> ssb2) != numSectorsForMat) |
| 498 | return S_FALSE; | 791 | return S_FALSE; |
| 499 | Mat.Alloc(numMatItems); | 792 | Mat.Alloc(numMatItems); |
| 500 | UInt32 i; | 793 | UInt32 sid = Get32(p32 + 15); // short-sector table SID |
| 501 | UInt32 sid = Get32(p + 0x3C); // short-sector table SID | 794 | if (numMatItems) |
| 502 | for (i = 0; i < numMatItems; i += numSidsInSec) | 795 | { |
| 796 | if (sid >= numFatItems || used[sid]) | ||
| 797 | return S_FALSE; | ||
| 798 | used[sid] = k_Used_ChainTo; | ||
| 799 | } | ||
| 800 | for (UInt32 i = 0; i < numMatItems; i += numSidsInSec) | ||
| 503 | { | 801 | { |
| 504 | RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i)) | ||
| 505 | if (sid >= numFatItems) | 802 | if (sid >= numFatItems) |
| 506 | return S_FALSE; | 803 | return S_FALSE; |
| 507 | sid = Fat[sid]; | 804 | RINOK(ReadIDs(inStream, sect, sid, Mat + i)) |
| 805 | sid = fat[sid]; | ||
| 508 | } | 806 | } |
| 509 | if (sid != NFatID::kEndOfChain) | 807 | if (sid != NFatID::kEndOfChain) |
| 510 | return S_FALSE; | 808 | return S_FALSE; |
| 511 | } | 809 | } |
| 512 | 810 | ||
| 513 | { | 811 | { |
| 514 | CByteBuffer used(numFatItems); | 812 | // ========== READ DIR ITEMS ========== |
| 515 | for (UInt32 i = 0; i < numFatItems; i++) | 813 | UInt32 sid = Get32(p32 + 12); // directory stream SID |
| 516 | used[i] = 0; | 814 | UInt32 numDirSectors_Processed = 0; |
| 517 | UInt32 sid = Get32(p + 0x30); // directory stream SID | 815 | if (sid >= numFatItems || used[sid]) |
| 518 | for (;;) | 816 | return S_FALSE; |
| 817 | used[sid] = k_Used_ChainTo; | ||
| 818 | do | ||
| 519 | { | 819 | { |
| 820 | // we need to check sid here becase kEndOfChain sid < numFatItems is required | ||
| 520 | if (sid >= numFatItems) | 821 | if (sid >= numFatItems) |
| 521 | return S_FALSE; | 822 | return S_FALSE; |
| 522 | if (used[sid]) | 823 | if (numDirSectors && numDirSectors_Processed >= numDirSectors) |
| 523 | return S_FALSE; | 824 | return S_FALSE; |
| 524 | used[sid] = 1; | 825 | numDirSectors_Processed++; |
| 525 | RINOK(ReadSector(inStream, sect, sectorSizeBits, sid)) | 826 | RINOK(ReadSector(inStream, sect, sid)) |
| 526 | for (UInt32 i = 0; i < sectSize; i += 128) | 827 | for (size_t i = 0; i < sectSize; i += (1 << 7)) |
| 527 | { | 828 | { |
| 528 | CItem item; | 829 | CItem item; |
| 529 | item.Parse(sect + i, mode64bit); | 830 | item.Level = k_Item_Level_Unused; |
| 831 | if (!item.Parse(sect + i, mode64bit)) | ||
| 832 | return S_FALSE; | ||
| 530 | // we use (item.Size) check here. | 833 | // we use (item.Size) check here. |
| 531 | // so we don't need additional overflow checks for (item.Size +) in another code | 834 | // so we don't need additional overflow checks for (item.Size +) in another code |
| 532 | if (item.Size >= ((UInt64)1 << 63)) | 835 | if ((UInt32)(item.Size >> 32) >= sectSize) // it's because FAT size is limited by (1 << 32) items. |
| 533 | return S_FALSE; | 836 | return S_FALSE; |
| 837 | |||
| 838 | if (Items.IsEmpty()) | ||
| 839 | { | ||
| 840 | if (item.Type != NItemType::kRootStorage | ||
| 841 | || item.LeftDid != kNoDid | ||
| 842 | || item.RightDid != kNoDid | ||
| 843 | || item.SonDid == 0) | ||
| 844 | return S_FALSE; | ||
| 845 | if (item.Sid != NFatID::kEndOfChain) | ||
| 846 | { | ||
| 847 | if (item.Sid >= numFatItems || used[item.Sid]) | ||
| 848 | return S_FALSE; | ||
| 849 | used[item.Sid] = k_Used_ChainTo; | ||
| 850 | } | ||
| 851 | } | ||
| 852 | else if (item.IsStorage()) | ||
| 853 | { | ||
| 854 | if (item.Size != 0) // by specification | ||
| 855 | return S_FALSE; | ||
| 856 | if (item.Sid != 0 // by specification | ||
| 857 | && item.Sid != NFatID::kFree) // NFatID::kFree is used in some AAF files | ||
| 858 | return S_FALSE; | ||
| 859 | } | ||
| 860 | // else if (item.Type == NItemType::kRootStorage) return S_FALSE; | ||
| 861 | else if (item.IsEmptyType()) | ||
| 862 | { | ||
| 863 | // kNoDid is expected in *Did fileds, but rare case MSI contains zero in all fields | ||
| 864 | if ((item.Sid != 0 // expected value | ||
| 865 | && item.Sid != NFatID::kFree // NFatID::kFree is used in some AAF files | ||
| 866 | && item.Sid != NFatID::kEndOfChain) // used by some MSI file | ||
| 867 | || (item.LeftDid != kNoDid && item.LeftDid) | ||
| 868 | || (item.RightDid != kNoDid && item.RightDid) | ||
| 869 | || (item.SonDid != kNoDid && item.SonDid) | ||
| 870 | // || item.Size != 0 // the check is disabled because some MSI file contains non zero | ||
| 871 | // || Get16(item.Name) != 0 // the check is disabled because some MSI file contains some name | ||
| 872 | ) | ||
| 873 | return S_FALSE; | ||
| 874 | } | ||
| 875 | else | ||
| 876 | { | ||
| 877 | if (item.Type != NItemType::kStream) | ||
| 878 | return S_FALSE; | ||
| 879 | // NItemType::kStream case | ||
| 880 | if (item.SonDid != kNoDid) // optional check | ||
| 881 | return S_FALSE; | ||
| 882 | if (item.Size == 0) | ||
| 883 | { | ||
| 884 | if (item.Sid != NFatID::kEndOfChain) | ||
| 885 | return S_FALSE; | ||
| 886 | } | ||
| 887 | else if (IsLargeStream(item.Size)) | ||
| 888 | { | ||
| 889 | if (item.Sid >= numFatItems || used[item.Sid]) | ||
| 890 | return S_FALSE; | ||
| 891 | used[item.Sid] = k_Used_ChainTo; | ||
| 892 | } | ||
| 893 | } | ||
| 894 | |||
| 534 | Items.Add(item); | 895 | Items.Add(item); |
| 535 | } | 896 | } |
| 536 | sid = Fat[sid]; | 897 | sid = fat[sid]; |
| 537 | if (sid == NFatID::kEndOfChain) | ||
| 538 | break; | ||
| 539 | } | 898 | } |
| 899 | while (sid != NFatID::kEndOfChain); | ||
| 540 | } | 900 | } |
| 541 | 901 | ||
| 542 | const CItem &root = Items[0]; | ||
| 543 | |||
| 544 | { | 902 | { |
| 903 | // root stream contains all data that stored with mini Sectors | ||
| 904 | const CItem &root = Items[0]; | ||
| 545 | UInt32 numSectorsInMiniStream; | 905 | UInt32 numSectorsInMiniStream; |
| 546 | { | 906 | { |
| 547 | UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits; | 907 | const UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits; |
| 548 | if (numSatSects64 > NFatID::kMaxValue) | 908 | if (numSatSects64 > NFatID::kMaxValue + 1) |
| 549 | return S_FALSE; | 909 | return S_FALSE; |
| 550 | numSectorsInMiniStream = (UInt32)numSatSects64; | 910 | numSectorsInMiniStream = (UInt32)numSatSects64; |
| 551 | } | 911 | } |
| 552 | NumSectorsInMiniStream = numSectorsInMiniStream; | ||
| 553 | MiniSids.Alloc(numSectorsInMiniStream); | ||
| 554 | { | 912 | { |
| 555 | UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits; | 913 | const UInt64 matSize64 = (root.Size + (1 << k_MiniSectorSizeBits) - 1) >> k_MiniSectorSizeBits; |
| 556 | if (matSize64 > NFatID::kMaxValue) | 914 | if (matSize64 > numMatItems) |
| 557 | return S_FALSE; | 915 | return S_FALSE; |
| 558 | MatSize = (UInt32)matSize64; | 916 | MatSize = (UInt32)matSize64; |
| 559 | if (numMatItems < MatSize) | ||
| 560 | return S_FALSE; | ||
| 561 | } | 917 | } |
| 562 | 918 | MiniSids.Alloc(numSectorsInMiniStream); | |
| 919 | UInt32 * const miniSids = MiniSids; | ||
| 563 | UInt32 sid = root.Sid; | 920 | UInt32 sid = root.Sid; |
| 564 | for (UInt32 i = 0; ; i++) | 921 | for (UInt32 i = 0; ; i++) |
| 565 | { | 922 | { |
| @@ -571,95 +928,186 @@ HRESULT CDatabase::Open(IInStream *inStream) | |||
| 571 | } | 928 | } |
| 572 | if (i >= numSectorsInMiniStream) | 929 | if (i >= numSectorsInMiniStream) |
| 573 | return S_FALSE; | 930 | return S_FALSE; |
| 574 | MiniSids[i] = sid; | ||
| 575 | if (sid >= numFatItems) | 931 | if (sid >= numFatItems) |
| 576 | return S_FALSE; | 932 | return S_FALSE; |
| 577 | sid = Fat[sid]; | 933 | miniSids[i] = sid; |
| 934 | sid = fat[sid]; | ||
| 578 | } | 935 | } |
| 936 | NumSectors_in_MiniStream = numSectorsInMiniStream; | ||
| 579 | } | 937 | } |
| 580 | 938 | ||
| 581 | RINOK(AddNode(-1, root.SonDid)) | 939 | |
| 582 | |||
| 583 | unsigned numCabs = 0; | ||
| 584 | |||
| 585 | FOR_VECTOR (i, Refs) | ||
| 586 | { | 940 | { |
| 587 | const CItem &item = Items[Refs[i].Did]; | 941 | /* |
| 588 | if (item.IsDir() || numCabs > 1) | 942 | MS DOCs: |
| 589 | continue; | 943 | The range lock sector covers file offsets 0x7FFFFF00-0x7FFFFFFF. |
| 590 | bool isMsiName; | 944 | These offsets are reserved for byte-range locking to support |
| 591 | const UString msiName = ConvertName(item.Name, isMsiName); | 945 | concurrency, transactions, and other compound file features. |
| 592 | if (isMsiName && !msiName.IsEmpty()) | 946 | The range lock sector MUST be allocated in the FAT and marked with |
| 593 | { | 947 | ENDOFCHAIN (0xFFFFFFFE), when the compound file grows beyond 2 GB. |
| 594 | // bool isThereExt = (msiName.Find(L'.') >= 0); | 948 | If the compound file is greater than 2 GB and then shrinks to below 2 GB, |
| 595 | bool isMsiSpec = (msiName[0] == k_Msi_SpecChar); | 949 | the range lock sector SHOULD be marked as FREESECT (0xFFFFFFFF) in the FAT. |
| 596 | if ((msiName.Len() >= 4 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(4), ".cab")) | 950 | */ |
| 597 | || (!isMsiSpec && msiName.Len() >= 3 && StringsAreEqualNoCase_Ascii(msiName.RightPtr(3), "exe")) | 951 | { |
| 598 | // || (!isMsiSpec && !isThereExt) | 952 | const UInt32 lockSector = (0x7fffffff >> sectorSizeBits) - 1; |
| 599 | ) | 953 | if (lockSector < numFatItems) |
| 600 | { | 954 | { |
| 601 | numCabs++; | 955 | if (used[lockSector]) |
| 602 | MainSubfile = (int)i; | 956 | return S_FALSE; |
| 957 | const UInt32 f = fat[lockSector]; | ||
| 958 | if (f == NFatID::kEndOfChain) | ||
| 959 | used[lockSector] = k_Used_ChainTo; // we use fake state to pass the check in loop below | ||
| 960 | else if (f != NFatID::kFree) | ||
| 961 | return S_FALSE; | ||
| 603 | } | 962 | } |
| 604 | } | 963 | } |
| 964 | for (size_t i = 0; i < numFatItems; i++) | ||
| 965 | { | ||
| 966 | UInt32 f = fat[i]; | ||
| 967 | const UInt32 u = ~(UInt32)used[i]; // (0xffffffff - used[i]) | ||
| 968 | if (f < NFatID::kMaxValue + 1) | ||
| 969 | f = NFatID::kEndOfChain; | ||
| 970 | if (f != u) | ||
| 971 | return S_FALSE; | ||
| 972 | } | ||
| 605 | } | 973 | } |
| 606 | |||
| 607 | if (numCabs > 1) | ||
| 608 | MainSubfile = -1; | ||
| 609 | 974 | ||
| 610 | { | 975 | { |
| 611 | FOR_VECTOR (t, Items) | 976 | // Don't move that code up, becase Check_Item uses Mat[] array. |
| 977 | FOR_VECTOR(t, Items) | ||
| 612 | { | 978 | { |
| 613 | Update_PhySize_WithItem(t); | 979 | RINOK(Check_Item(t)) |
| 614 | } | 980 | } |
| 615 | } | 981 | } |
| 982 | |||
| 983 | RINOK(AddNodes()) | ||
| 984 | |||
| 985 | { | ||
| 986 | // some msi (in rare cases) have unaligned size of archive, | ||
| 987 | // unaligned size of compond files is also possible if we create just one stream | ||
| 988 | // where there is no padding data after payload data in last cluster of archive | ||
| 989 | UInt64 fileSize; | ||
| 990 | RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize)) | ||
| 991 | if ( fileSize < PhySize | ||
| 992 | && fileSize > PhySize - sectSize | ||
| 993 | && fileSize >= PhySize_Unaligned | ||
| 994 | && PhySize_Unaligned > PhySize - sectSize) | ||
| 995 | PhySize = PhySize_Unaligned; | ||
| 996 | } | ||
| 997 | |||
| 998 | bool isMsi = false; | ||
| 616 | { | 999 | { |
| 617 | if (PhySize != PhySize_Aligned) | 1000 | FOR_VECTOR (i, Refs) |
| 618 | { | 1001 | { |
| 619 | /* some msi (in rare cases) have unaligned size of archive, | 1002 | const CItem &item = Items[Refs[i].Did]; |
| 620 | where there is no padding data after payload data in last cluster of archive */ | 1003 | if (item.IsDir()) |
| 621 | UInt64 fileSize; | 1004 | continue; |
| 622 | RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize)) | 1005 | if (item.AreMsiChars()) |
| 623 | if (PhySize != fileSize) | 1006 | // if (item.IsSpecMsiName()) |
| 624 | PhySize = PhySize_Aligned; | 1007 | { |
| 1008 | isMsi = true; | ||
| 1009 | break; | ||
| 1010 | } | ||
| 625 | } | 1011 | } |
| 626 | } | 1012 | } |
| 1013 | |||
| 1014 | // IsMsi = isMsi; | ||
| 1015 | if (isMsi) | ||
| 627 | { | 1016 | { |
| 628 | FOR_VECTOR (t, Items) | 1017 | unsigned numCabs = 0; |
| 1018 | UString name; | ||
| 1019 | FOR_VECTOR (i, Refs) | ||
| 629 | { | 1020 | { |
| 630 | const CItem &item = Items[t]; | 1021 | const CItem &item = Items[Refs[i].Did]; |
| 631 | 1022 | if (item.IsDir() /* || item.IsSpecMsiName() */) | |
| 632 | if (IsMsiName(item.Name)) | 1023 | continue; |
| 1024 | MsiName_To_FileName(item.Name, name); | ||
| 1025 | if ( (name.Len() >= 4 && StringsAreEqualNoCase_Ascii(name.RightPtr(4), ".cab")) | ||
| 1026 | || (name.Len() >= 3 && StringsAreEqualNoCase_Ascii(name.RightPtr(3), "exe")) | ||
| 1027 | ) | ||
| 633 | { | 1028 | { |
| 634 | Type = k_Type_Msi; | 1029 | numCabs++; |
| 635 | if (memcmp(item.Name, kMspSequence, kMspSequence_Size) == 0) | 1030 | if (numCabs > 1) |
| 636 | { | 1031 | { |
| 637 | Type = k_Type_Msp; | 1032 | MainSubfile = -1; |
| 638 | break; | 1033 | break; |
| 639 | } | 1034 | } |
| 640 | continue; | 1035 | MainSubfile = (int)i; |
| 641 | } | ||
| 642 | if (AreEqualNames(item.Name, "WordDocument")) | ||
| 643 | { | ||
| 644 | Type = k_Type_Doc; | ||
| 645 | break; | ||
| 646 | } | 1036 | } |
| 647 | if (AreEqualNames(item.Name, "PowerPoint Document")) | 1037 | } |
| 1038 | } | ||
| 1039 | |||
| 1040 | if (isMsi) // we provide msi priority over AAF | ||
| 1041 | Type = k_Type_Msi; | ||
| 1042 | if (Type != k_Type_Aaf) | ||
| 1043 | { | ||
| 1044 | FOR_VECTOR (i, Refs) | ||
| 1045 | { | ||
| 1046 | const CItem &item = Items[Refs[i].Did]; | ||
| 1047 | if (item.IsDir()) | ||
| 1048 | continue; | ||
| 1049 | const Byte *name = item.Name; | ||
| 1050 | // if (IsMsiName(name)) | ||
| 1051 | if (isMsi) | ||
| 648 | { | 1052 | { |
| 649 | Type = k_Type_Ppt; | 1053 | if (memcmp(name, k_Sequence_msp, sizeof(k_Sequence_msp)) == 0) |
| 650 | break; | 1054 | { |
| 1055 | Type = k_Type_Msp; | ||
| 1056 | break; | ||
| 1057 | } | ||
| 1058 | if (memcmp(name, k_Sequence_msm, sizeof(k_Sequence_msm)) == 0) | ||
| 1059 | { | ||
| 1060 | Type = k_Type_Msm; | ||
| 1061 | break; | ||
| 1062 | } | ||
| 651 | } | 1063 | } |
| 652 | if (AreEqualNames(item.Name, "Workbook")) | 1064 | else |
| 653 | { | 1065 | { |
| 654 | Type = k_Type_Xls; | 1066 | if (AreEqualNames(name, "WordDocument")) |
| 655 | break; | 1067 | { |
| 1068 | Type = k_Type_Doc; | ||
| 1069 | break; | ||
| 1070 | } | ||
| 1071 | if (AreEqualNames(name, "PowerPoint Document")) | ||
| 1072 | { | ||
| 1073 | Type = k_Type_Ppt; | ||
| 1074 | break; | ||
| 1075 | } | ||
| 1076 | if (AreEqualNames(name, "Workbook")) | ||
| 1077 | { | ||
| 1078 | Type = k_Type_Xls; | ||
| 1079 | break; | ||
| 1080 | } | ||
| 656 | } | 1081 | } |
| 657 | } | 1082 | } |
| 658 | } | 1083 | } |
| 659 | 1084 | ||
| 1085 | #ifdef Z7_COMPOUND_SHOW_DELETED | ||
| 1086 | { | ||
| 1087 | // we skip Items[0] that is root item | ||
| 1088 | for (unsigned t = 1; t < Items.Size(); t++) | ||
| 1089 | { | ||
| 1090 | const CItem &item = Items[t]; | ||
| 1091 | if ( | ||
| 1092 | #if 1 // 0 for debug to show empty files | ||
| 1093 | item.IsEmptyType() || | ||
| 1094 | #endif | ||
| 1095 | !item.IsLevel_Unused()) | ||
| 1096 | continue; | ||
| 1097 | CRef ref; | ||
| 1098 | ref.Parent = k_Ref_Parent_Root; | ||
| 1099 | ref.Did = t; | ||
| 1100 | Refs.Add(ref); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | #endif | ||
| 1104 | |||
| 1105 | HeadersError = false; | ||
| 660 | return S_OK; | 1106 | return S_OK; |
| 661 | } | 1107 | } |
| 662 | 1108 | ||
| 1109 | |||
| 1110 | |||
| 663 | Z7_CLASS_IMP_CHandler_IInArchive_1( | 1111 | Z7_CLASS_IMP_CHandler_IInArchive_1( |
| 664 | IInArchiveGetStream | 1112 | IInArchiveGetStream |
| 665 | ) | 1113 | ) |
| @@ -674,13 +1122,15 @@ static const Byte kProps[] = | |||
| 674 | kpidPackSize, | 1122 | kpidPackSize, |
| 675 | kpidCTime, | 1123 | kpidCTime, |
| 676 | kpidMTime | 1124 | kpidMTime |
| 1125 | // , kpidCharacts // for debug | ||
| 677 | }; | 1126 | }; |
| 678 | 1127 | ||
| 679 | static const Byte kArcProps[] = | 1128 | static const Byte kArcProps[] = |
| 680 | { | 1129 | { |
| 681 | kpidExtension, | 1130 | kpidExtension, |
| 682 | kpidClusterSize, | 1131 | kpidClusterSize |
| 683 | kpidSectorSize | 1132 | // , kpidSectorSize |
| 1133 | // , kpidFreeSpace | ||
| 684 | }; | 1134 | }; |
| 685 | 1135 | ||
| 686 | IMP_IInArchive_Props | 1136 | IMP_IInArchive_Props |
| @@ -695,9 +1145,20 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) | |||
| 695 | case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break; | 1145 | case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break; |
| 696 | case kpidPhySize: prop = _db.PhySize; break; | 1146 | case kpidPhySize: prop = _db.PhySize; break; |
| 697 | case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; | 1147 | case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break; |
| 698 | case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; | 1148 | // case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break; |
| 699 | case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; | 1149 | case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break; |
| 1150 | // case kpidFreeSpace: prop = _db.FreeSize; break; | ||
| 700 | case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break; | 1151 | case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break; |
| 1152 | case kpidErrorFlags: | ||
| 1153 | { | ||
| 1154 | UInt32 v = 0; | ||
| 1155 | if (!_db.IsArc) | ||
| 1156 | v |= kpv_ErrorFlags_IsNotArc; | ||
| 1157 | if (_db.HeadersError) | ||
| 1158 | v |= kpv_ErrorFlags_HeadersError; | ||
| 1159 | prop = v; | ||
| 1160 | break; | ||
| 1161 | } | ||
| 701 | } | 1162 | } |
| 702 | prop.Detach(value); | 1163 | prop.Detach(value); |
| 703 | return S_OK; | 1164 | return S_OK; |
| @@ -719,6 +1180,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 719 | case kpidMTime: prop = item.MTime; break; | 1180 | case kpidMTime: prop = item.MTime; break; |
| 720 | case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; | 1181 | case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break; |
| 721 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; | 1182 | case kpidSize: if (!item.IsDir()) prop = item.Size; break; |
| 1183 | // case kpidCharacts: prop = item.Level; break; | ||
| 722 | } | 1184 | } |
| 723 | prop.Detach(value); | 1185 | prop.Detach(value); |
| 724 | return S_OK; | 1186 | return S_OK; |
| @@ -727,17 +1189,17 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 727 | 1189 | ||
| 728 | Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, | 1190 | Z7_COM7F_IMF(CHandler::Open(IInStream *inStream, |
| 729 | const UInt64 * /* maxCheckStartPosition */, | 1191 | const UInt64 * /* maxCheckStartPosition */, |
| 730 | IArchiveOpenCallback * /* openArchiveCallback */)) | 1192 | IArchiveOpenCallback *openArchiveCallback)) |
| 731 | { | 1193 | { |
| 732 | COM_TRY_BEGIN | 1194 | COM_TRY_BEGIN |
| 733 | Close(); | 1195 | Close(); |
| 734 | try | 1196 | _db.OpenCallback = openArchiveCallback; |
| 1197 | // try | ||
| 735 | { | 1198 | { |
| 736 | if (_db.Open(inStream) != S_OK) | 1199 | RINOK(_db.Open(inStream)) |
| 737 | return S_FALSE; | ||
| 738 | _stream = inStream; | 1200 | _stream = inStream; |
| 739 | } | 1201 | } |
| 740 | catch(...) { return S_FALSE; } | 1202 | // catch(...) { return S_FALSE; } |
| 741 | return S_OK; | 1203 | return S_OK; |
| 742 | COM_TRY_END | 1204 | COM_TRY_END |
| 743 | } | 1205 | } |
| @@ -775,52 +1237,57 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 775 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; | 1237 | CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; |
| 776 | lps->Init(extractCallback, false); | 1238 | lps->Init(extractCallback, false); |
| 777 | 1239 | ||
| 778 | for (i = 0; i < numItems; i++) | 1240 | for (i = 0;; i++) |
| 779 | { | 1241 | { |
| 780 | lps->InSize = totalPackSize; | 1242 | lps->InSize = totalPackSize; |
| 781 | lps->OutSize = totalSize; | 1243 | lps->OutSize = totalSize; |
| 782 | RINOK(lps->SetCur()) | 1244 | RINOK(lps->SetCur()) |
| 1245 | if (i >= numItems) | ||
| 1246 | break; | ||
| 1247 | |||
| 783 | const UInt32 index = allFilesMode ? i : indices[i]; | 1248 | const UInt32 index = allFilesMode ? i : indices[i]; |
| 784 | const CItem &item = _db.Items[_db.Refs[index].Did]; | 1249 | const CItem &item = _db.Items[_db.Refs[index].Did]; |
| 785 | Int32 res; | 1250 | Int32 res; |
| 786 | { | ||
| 787 | CMyComPtr<ISequentialOutStream> outStream; | ||
| 788 | const Int32 askMode = testMode ? | ||
| 789 | NExtract::NAskMode::kTest : | ||
| 790 | NExtract::NAskMode::kExtract; | ||
| 791 | RINOK(extractCallback->GetStream(index, &outStream, askMode)) | ||
| 792 | |||
| 793 | if (item.IsDir()) | ||
| 794 | { | 1251 | { |
| 1252 | CMyComPtr<ISequentialOutStream> outStream; | ||
| 1253 | const Int32 askMode = testMode ? | ||
| 1254 | NExtract::NAskMode::kTest : | ||
| 1255 | NExtract::NAskMode::kExtract; | ||
| 1256 | RINOK(extractCallback->GetStream(index, &outStream, askMode)) | ||
| 1257 | |||
| 1258 | if (item.IsDir()) | ||
| 1259 | { | ||
| 1260 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
| 1261 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
| 1262 | continue; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | totalPackSize += _db.GetItemPackSize(item.Size); | ||
| 1266 | totalSize += item.Size; | ||
| 1267 | |||
| 1268 | if (!testMode && !outStream) | ||
| 1269 | continue; | ||
| 795 | RINOK(extractCallback->PrepareOperation(askMode)) | 1270 | RINOK(extractCallback->PrepareOperation(askMode)) |
| 796 | RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) | ||
| 797 | continue; | ||
| 798 | } | ||
| 799 | |||
| 800 | totalPackSize += _db.GetItemPackSize(item.Size); | ||
| 801 | totalSize += item.Size; | ||
| 802 | |||
| 803 | if (!testMode && !outStream) | ||
| 804 | continue; | ||
| 805 | RINOK(extractCallback->PrepareOperation(askMode)) | ||
| 806 | res = NExtract::NOperationResult::kDataError; | ||
| 807 | CMyComPtr<ISequentialInStream> inStream; | ||
| 808 | HRESULT hres = GetStream(index, &inStream); | ||
| 809 | if (hres == S_FALSE) | ||
| 810 | res = NExtract::NOperationResult::kDataError; | 1271 | res = NExtract::NOperationResult::kDataError; |
| 811 | else if (hres == E_NOTIMPL) | 1272 | CMyComPtr<ISequentialInStream> inStream; |
| 812 | res = NExtract::NOperationResult::kUnsupportedMethod; | 1273 | const HRESULT hres = GetStream(index, &inStream); |
| 813 | else | 1274 | if (hres == S_FALSE) |
| 814 | { | 1275 | res = NExtract::NOperationResult::kDataError; |
| 815 | RINOK(hres) | 1276 | /* |
| 816 | if (inStream) | 1277 | else if (hres == E_NOTIMPL) |
| 1278 | res = NExtract::NOperationResult::kUnsupportedMethod; | ||
| 1279 | */ | ||
| 1280 | else | ||
| 817 | { | 1281 | { |
| 818 | RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps)) | 1282 | RINOK(hres) |
| 819 | if (copyCoder->TotalSize == item.Size) | 1283 | if (inStream) |
| 820 | res = NExtract::NOperationResult::kOK; | 1284 | { |
| 1285 | RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps)) | ||
| 1286 | if (copyCoder->TotalSize == item.Size) | ||
| 1287 | res = NExtract::NOperationResult::kOK; | ||
| 1288 | } | ||
| 821 | } | 1289 | } |
| 822 | } | 1290 | } |
| 823 | } | ||
| 824 | RINOK(extractCallback->SetOperationResult(res)) | 1291 | RINOK(extractCallback->SetOperationResult(res)) |
| 825 | } | 1292 | } |
| 826 | return S_OK; | 1293 | return S_OK; |
| @@ -839,20 +1306,64 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 839 | *stream = NULL; | 1306 | *stream = NULL; |
| 840 | const UInt32 itemIndex = _db.Refs[index].Did; | 1307 | const UInt32 itemIndex = _db.Refs[index].Did; |
| 841 | const CItem &item = _db.Items[itemIndex]; | 1308 | const CItem &item = _db.Items[itemIndex]; |
| 1309 | if (item.IsDir()) | ||
| 1310 | return S_FALSE; | ||
| 1311 | const bool isLargeStream = (itemIndex == 0 || IsLargeStream(item.Size)); | ||
| 1312 | if (!isLargeStream) | ||
| 1313 | { | ||
| 1314 | CBufferInStream *streamSpec = new CBufferInStream; | ||
| 1315 | CMyComPtr<IInStream> streamTemp = streamSpec; | ||
| 1316 | |||
| 1317 | UInt32 size = (UInt32)item.Size; | ||
| 1318 | streamSpec->Buf.Alloc(size); | ||
| 1319 | streamSpec->Init(); | ||
| 1320 | |||
| 1321 | UInt32 sid = item.Sid; | ||
| 1322 | Byte *dest = streamSpec->Buf; | ||
| 1323 | |||
| 1324 | UInt64 phyPos = 0; | ||
| 1325 | while (size) | ||
| 1326 | { | ||
| 1327 | if (sid >= _db.MatSize) | ||
| 1328 | return S_FALSE; | ||
| 1329 | const unsigned subBits = _db.SectorSizeBits - k_MiniSectorSizeBits; | ||
| 1330 | const UInt32 fid = sid >> subBits; | ||
| 1331 | if (fid >= _db.NumSectors_in_MiniStream) | ||
| 1332 | return false; | ||
| 1333 | const UInt64 offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) + | ||
| 1334 | ((sid & ((1u << subBits) - 1)) << k_MiniSectorSizeBits); | ||
| 1335 | if (phyPos != offset) | ||
| 1336 | { | ||
| 1337 | RINOK(InStream_SeekSet(_stream, offset)) | ||
| 1338 | phyPos = offset; | ||
| 1339 | } | ||
| 1340 | UInt32 readSize = (UInt32)1 << k_MiniSectorSizeBits; | ||
| 1341 | if (readSize > size) | ||
| 1342 | readSize = size; | ||
| 1343 | RINOK(ReadStream_FALSE(_stream, dest, readSize)) | ||
| 1344 | phyPos += readSize; | ||
| 1345 | dest += readSize; | ||
| 1346 | sid = _db.Mat[sid]; | ||
| 1347 | size -= readSize; | ||
| 1348 | } | ||
| 1349 | if (sid != NFatID::kEndOfChain) | ||
| 1350 | return S_FALSE; | ||
| 1351 | *stream = streamTemp.Detach(); | ||
| 1352 | return S_OK; | ||
| 1353 | } | ||
| 1354 | |||
| 842 | CClusterInStream *streamSpec = new CClusterInStream; | 1355 | CClusterInStream *streamSpec = new CClusterInStream; |
| 843 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | 1356 | CMyComPtr<ISequentialInStream> streamTemp = streamSpec; |
| 844 | streamSpec->Stream = _stream; | 1357 | streamSpec->Stream = _stream; |
| 845 | streamSpec->StartOffset = 0; | 1358 | streamSpec->StartOffset = 0; |
| 846 | 1359 | const unsigned bsLog = _db.SectorSizeBits; | |
| 847 | const bool isLargeStream = (itemIndex == 0 || _db.IsLargeStream(item.Size)); | ||
| 848 | const unsigned bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits; | ||
| 849 | streamSpec->BlockSizeLog = bsLog; | 1360 | streamSpec->BlockSizeLog = bsLog; |
| 850 | streamSpec->Size = item.Size; | 1361 | streamSpec->Size = item.Size; |
| 851 | 1362 | ||
| 852 | const UInt32 clusterSize = (UInt32)1 << bsLog; | 1363 | const UInt32 clusterSize = (UInt32)1 << bsLog; |
| 853 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; | 1364 | const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog; |
| 854 | if (numClusters64 >= ((UInt32)1 << 31)) | 1365 | if (numClusters64 > _db.FatSize) |
| 855 | return E_NOTIMPL; | 1366 | return S_FALSE; |
| 856 | streamSpec->Vector.ClearAndReserve((unsigned)numClusters64); | 1367 | streamSpec->Vector.ClearAndReserve((unsigned)numClusters64); |
| 857 | UInt32 sid = item.Sid; | 1368 | UInt32 sid = item.Sid; |
| 858 | UInt64 size = item.Size; | 1369 | UInt64 size = item.Size; |
| @@ -861,21 +1372,10 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 861 | { | 1372 | { |
| 862 | for (;; size -= clusterSize) | 1373 | for (;; size -= clusterSize) |
| 863 | { | 1374 | { |
| 864 | if (isLargeStream) | 1375 | if (sid >= _db.FatSize) |
| 865 | { | 1376 | return S_FALSE; |
| 866 | if (sid >= _db.FatSize) | 1377 | streamSpec->Vector.AddInReserved(sid + 1); |
| 867 | return S_FALSE; | 1378 | sid = _db.Fat[sid]; |
| 868 | streamSpec->Vector.AddInReserved(sid + 1); | ||
| 869 | sid = _db.Fat[sid]; | ||
| 870 | } | ||
| 871 | else | ||
| 872 | { | ||
| 873 | UInt64 val = 0; | ||
| 874 | if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32) | ||
| 875 | return S_FALSE; | ||
| 876 | streamSpec->Vector.AddInReserved((UInt32)val); | ||
| 877 | sid = _db.Mat[sid]; | ||
| 878 | } | ||
| 879 | if (size <= clusterSize) | 1379 | if (size <= clusterSize) |
| 880 | break; | 1380 | break; |
| 881 | } | 1381 | } |
| @@ -889,7 +1389,7 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 889 | } | 1389 | } |
| 890 | 1390 | ||
| 891 | REGISTER_ARC_I( | 1391 | REGISTER_ARC_I( |
| 892 | "Compound", "msi msp doc xls ppt", NULL, 0xE5, | 1392 | "Compound", "msi msp msm doc xls ppt aaf", NULL, 0xe5, |
| 893 | kSignature, | 1393 | kSignature, |
| 894 | 0, | 1394 | 0, |
| 895 | 0, | 1395 | 0, |
diff --git a/CPP/7zip/Archive/CpioHandler.cpp b/CPP/7zip/Archive/CpioHandler.cpp index 62184f0..e1d6d81 100644 --- a/CPP/7zip/Archive/CpioHandler.cpp +++ b/CPP/7zip/Archive/CpioHandler.cpp | |||
| @@ -927,7 +927,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 927 | { | 927 | { |
| 928 | #ifdef _WIN32 | 928 | #ifdef _WIN32 |
| 929 | UString u; | 929 | UString u; |
| 930 | ConvertUTF8ToUnicode(item.Name, u); | 930 | ConvertUTF8ToUnicode(s, u); |
| 931 | #else | 931 | #else |
| 932 | const UString u = MultiByteToUnicodeString(s, CP_OEMCP); | 932 | const UString u = MultiByteToUnicodeString(s, CP_OEMCP); |
| 933 | #endif | 933 | #endif |
diff --git a/CPP/7zip/Archive/QcowHandler.cpp b/CPP/7zip/Archive/QcowHandler.cpp index b072880..6edf86d 100644 --- a/CPP/7zip/Archive/QcowHandler.cpp +++ b/CPP/7zip/Archive/QcowHandler.cpp | |||
| @@ -482,6 +482,10 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | |||
| 482 | if (_phySize < headerSize) | 482 | if (_phySize < headerSize) |
| 483 | _phySize = headerSize; | 483 | _phySize = headerSize; |
| 484 | 484 | ||
| 485 | // we use 32 MiB limit for L1 size, as QEMU with QCOW_MAX_L1_SIZE limit. | ||
| 486 | if (l1Size > (1u << 22)) // if (l1Size > (1u << (sizeof(size_t) * 8 - 4))) | ||
| 487 | return S_FALSE; | ||
| 488 | |||
| 485 | _isArc = true; | 489 | _isArc = true; |
| 486 | { | 490 | { |
| 487 | const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8); | 491 | const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8); |
| @@ -519,7 +523,6 @@ HRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback) | |||
| 519 | } | 523 | } |
| 520 | CObjArray<UInt64> table64(l1Size); | 524 | CObjArray<UInt64> table64(l1Size); |
| 521 | { | 525 | { |
| 522 | // if ((t1SizeBytes >> 3) != l1Size) return S_FALSE; | ||
| 523 | RINOK(InStream_SeekSet(stream, l1Offset)) | 526 | RINOK(InStream_SeekSet(stream, l1Offset)) |
| 524 | RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes)) | 527 | RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes)) |
| 525 | } | 528 | } |
diff --git a/CPP/7zip/Archive/Rar/Rar5Handler.cpp b/CPP/7zip/Archive/Rar/Rar5Handler.cpp index a639d8b..c15ff52 100644 --- a/CPP/7zip/Archive/Rar/Rar5Handler.cpp +++ b/CPP/7zip/Archive/Rar/Rar5Handler.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "../../../Common/ComTry.h" | 8 | #include "../../../Common/ComTry.h" |
| 9 | #include "../../../Common/IntToString.h" | 9 | #include "../../../Common/IntToString.h" |
| 10 | #include "../../../Common/MyBuffer2.h" | 10 | #include "../../../Common/MyBuffer2.h" |
| 11 | #include "../../../Common/MyLinux.h" | ||
| 11 | #include "../../../Common/UTFConvert.h" | 12 | #include "../../../Common/UTFConvert.h" |
| 12 | 13 | ||
| 13 | #include "../../../Windows/PropVariantUtils.h" | 14 | #include "../../../Windows/PropVariantUtils.h" |
| @@ -1184,7 +1185,15 @@ HRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSiz | |||
| 1184 | 1185 | ||
| 1185 | const UInt64 processedSize = outStream->GetPos(); | 1186 | const UInt64 processedSize = outStream->GetPos(); |
| 1186 | if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) | 1187 | if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size) |
| 1187 | res = S_FALSE; | 1188 | { |
| 1189 | // rar_v7.13-: linux archive contains symLink with (packSize == 0 && lastItem.Size != 0) | ||
| 1190 | // v25.02: we ignore such record in rar headers: | ||
| 1191 | if (packSize != 0 | ||
| 1192 | || method != 0 | ||
| 1193 | || lastItem.HostOS != kHost_Unix | ||
| 1194 | || !MY_LIN_S_ISLNK(lastItem.Attrib)) | ||
| 1195 | res = S_FALSE; | ||
| 1196 | } | ||
| 1188 | 1197 | ||
| 1189 | // if (res == S_OK) | 1198 | // if (res == S_OK) |
| 1190 | { | 1199 | { |
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp index dfbad33..6c53847 100644 --- a/CPP/7zip/Archive/Rar/RarHandler.cpp +++ b/CPP/7zip/Archive/Rar/RarHandler.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "../../../Common/ComTry.h" | 7 | #include "../../../Common/ComTry.h" |
| 8 | #include "../../../Common/IntToString.h" | 8 | #include "../../../Common/IntToString.h" |
| 9 | #include "../../../Common/MyBuffer2.h" | 9 | #include "../../../Common/MyBuffer2.h" |
| 10 | #include "../../../Common/MyLinux.h" | ||
| 10 | #include "../../../Common/UTFConvert.h" | 11 | #include "../../../Common/UTFConvert.h" |
| 11 | 12 | ||
| 12 | #include "../../../Windows/PropVariantUtils.h" | 13 | #include "../../../Windows/PropVariantUtils.h" |
| @@ -70,8 +71,14 @@ bool CItem::IsDir() const | |||
| 70 | case NHeader::NFile::kHostMSDOS: | 71 | case NHeader::NFile::kHostMSDOS: |
| 71 | case NHeader::NFile::kHostOS2: | 72 | case NHeader::NFile::kHostOS2: |
| 72 | case NHeader::NFile::kHostWin32: | 73 | case NHeader::NFile::kHostWin32: |
| 73 | if ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0) | 74 | if (Attrib & FILE_ATTRIBUTE_DIRECTORY) |
| 74 | return true; | 75 | return true; |
| 76 | break; | ||
| 77 | case NHeader::NFile::kHostUnix: | ||
| 78 | case NHeader::NFile::kHostBeOS: | ||
| 79 | if (MY_LIN_S_ISDIR(Attrib)) | ||
| 80 | return true; | ||
| 81 | break; | ||
| 75 | } | 82 | } |
| 76 | return false; | 83 | return false; |
| 77 | } | 84 | } |
| @@ -86,11 +93,20 @@ UInt32 CItem::GetWinAttrib() const | |||
| 86 | case NHeader::NFile::kHostWin32: | 93 | case NHeader::NFile::kHostWin32: |
| 87 | a = Attrib; | 94 | a = Attrib; |
| 88 | break; | 95 | break; |
| 96 | case NHeader::NFile::kHostUnix: | ||
| 97 | case NHeader::NFile::kHostBeOS: | ||
| 98 | a = Attrib << 16; | ||
| 99 | a |= 0x8000; // add posix mode marker | ||
| 100 | break; | ||
| 101 | // case NHeader::NFile::kHostMacOS: | ||
| 102 | // kHostMacOS was used only by some very old rare case rar. | ||
| 103 | // New rar4-rar7 for macos probably uses kHostUnix. | ||
| 104 | // So we process kHostMacOS without attribute parsing: | ||
| 89 | default: | 105 | default: |
| 90 | a = 0; // must be converted from unix value; | 106 | a = 0; |
| 91 | } | 107 | } |
| 92 | if (IsDir()) | 108 | if (IsDir()) |
| 93 | a |= NHeader::NFile::kWinFileDirectoryAttributeMask; | 109 | a |= FILE_ATTRIBUTE_DIRECTORY; |
| 94 | return a; | 110 | return a; |
| 95 | } | 111 | } |
| 96 | 112 | ||
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp index 29f28e8..5761ea3 100644 --- a/CPP/7zip/Archive/Tar/TarHandler.cpp +++ b/CPP/7zip/Archive/Tar/TarHandler.cpp | |||
| @@ -65,7 +65,7 @@ static const Byte kArcProps[] = | |||
| 65 | kpidComment | 65 | kpidComment |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | static const char *k_Characts_Prefix = "PREFIX"; | 68 | static const char * const k_Characts_Prefix = "PREFIX"; |
| 69 | 69 | ||
| 70 | IMP_IInArchive_Props | 70 | IMP_IInArchive_Props |
| 71 | IMP_IInArchive_ArcProps | 71 | IMP_IInArchive_ArcProps |
| @@ -684,10 +684,14 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val | |||
| 684 | s.Add_OptSpaced("SCHILY.fflags="); | 684 | s.Add_OptSpaced("SCHILY.fflags="); |
| 685 | s += item->SCHILY_fflags; | 685 | s += item->SCHILY_fflags; |
| 686 | } | 686 | } |
| 687 | if (item->Is_Sparse()) | ||
| 688 | s.Add_OptSpaced("SPARSE"); | ||
| 687 | if (item->IsThereWarning()) | 689 | if (item->IsThereWarning()) |
| 688 | s.Add_OptSpaced("WARNING"); | 690 | s.Add_OptSpaced("WARNING"); |
| 689 | if (item->HeaderError) | 691 | if (item->HeaderError) |
| 690 | s.Add_OptSpaced("ERROR"); | 692 | s.Add_OptSpaced("ERROR"); |
| 693 | if (item->Method_Error) | ||
| 694 | s.Add_OptSpaced("METHOD_ERROR"); | ||
| 691 | if (item->Pax_Error) | 695 | if (item->Pax_Error) |
| 692 | s.Add_OptSpaced("PAX_error"); | 696 | s.Add_OptSpaced("PAX_error"); |
| 693 | if (!item->PaxExtra.RawLines.IsEmpty()) | 697 | if (!item->PaxExtra.RawLines.IsEmpty()) |
| @@ -812,11 +816,16 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, | |||
| 812 | inStream2 = inStream; | 816 | inStream2 = inStream; |
| 813 | else | 817 | else |
| 814 | { | 818 | { |
| 815 | GetStream(index, &inStream2); | 819 | const HRESULT hres = GetStream(index, &inStream2); |
| 816 | if (!inStream2) | 820 | if (hres == E_NOTIMPL) |
| 817 | return E_FAIL; | 821 | opRes = NExtract::NOperationResult::kHeadersError; // kUnsupportedMethod |
| 822 | else if (!inStream2) | ||
| 823 | { | ||
| 824 | opRes = NExtract::NOperationResult::kDataError; | ||
| 825 | // return E_FAIL; | ||
| 826 | } | ||
| 818 | } | 827 | } |
| 819 | 828 | if (opRes == NExtract::NOperationResult::kOK) | |
| 820 | { | 829 | { |
| 821 | if (item->Is_SymLink()) | 830 | if (item->Is_SymLink()) |
| 822 | { | 831 | { |
| @@ -855,9 +864,9 @@ Z7_CLASS_IMP_IInStream( | |||
| 855 | bool _needStartSeek; | 864 | bool _needStartSeek; |
| 856 | 865 | ||
| 857 | public: | 866 | public: |
| 867 | unsigned ItemIndex; | ||
| 858 | CHandler *Handler; | 868 | CHandler *Handler; |
| 859 | CMyComPtr<IUnknown> HandlerRef; | 869 | CMyComPtr<IUnknown> HandlerRef; |
| 860 | unsigned ItemIndex; | ||
| 861 | CRecordVector<UInt64> PhyOffsets; | 870 | CRecordVector<UInt64> PhyOffsets; |
| 862 | 871 | ||
| 863 | void Init() | 872 | void Init() |
| @@ -879,7 +888,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 879 | if (_virtPos >= item.Size) | 888 | if (_virtPos >= item.Size) |
| 880 | return S_OK; | 889 | return S_OK; |
| 881 | { | 890 | { |
| 882 | UInt64 rem = item.Size - _virtPos; | 891 | const UInt64 rem = item.Size - _virtPos; |
| 883 | if (size > rem) | 892 | if (size > rem) |
| 884 | size = (UInt32)rem; | 893 | size = (UInt32)rem; |
| 885 | } | 894 | } |
| @@ -903,17 +912,17 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 903 | } | 912 | } |
| 904 | 913 | ||
| 905 | const CSparseBlock &sb = item.SparseBlocks[left]; | 914 | const CSparseBlock &sb = item.SparseBlocks[left]; |
| 906 | UInt64 relat = _virtPos - sb.Offset; | 915 | const UInt64 relat = _virtPos - sb.Offset; |
| 907 | 916 | ||
| 908 | if (_virtPos >= sb.Offset && relat < sb.Size) | 917 | if (_virtPos >= sb.Offset && relat < sb.Size) |
| 909 | { | 918 | { |
| 910 | UInt64 rem = sb.Size - relat; | 919 | const UInt64 rem = sb.Size - relat; |
| 911 | if (size > rem) | 920 | if (size > rem) |
| 912 | size = (UInt32)rem; | 921 | size = (UInt32)rem; |
| 913 | UInt64 phyPos = PhyOffsets[left] + relat; | 922 | const UInt64 phyPos = PhyOffsets[left] + relat; |
| 914 | if (_needStartSeek || _phyPos != phyPos) | 923 | if (_needStartSeek || _phyPos != phyPos) |
| 915 | { | 924 | { |
| 916 | RINOK(InStream_SeekSet(Handler->_stream, (item.Get_DataPos() + phyPos))) | 925 | RINOK(InStream_SeekSet(Handler->_stream, item.Get_DataPos() + phyPos)) |
| 917 | _needStartSeek = false; | 926 | _needStartSeek = false; |
| 918 | _phyPos = phyPos; | 927 | _phyPos = phyPos; |
| 919 | } | 928 | } |
| @@ -927,7 +936,7 @@ Z7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize) | |||
| 927 | next = sb.Offset; | 936 | next = sb.Offset; |
| 928 | else if (left + 1 < item.SparseBlocks.Size()) | 937 | else if (left + 1 < item.SparseBlocks.Size()) |
| 929 | next = item.SparseBlocks[left + 1].Offset; | 938 | next = item.SparseBlocks[left + 1].Offset; |
| 930 | UInt64 rem = next - _virtPos; | 939 | const UInt64 rem = next - _virtPos; |
| 931 | if (size > rem) | 940 | if (size > rem) |
| 932 | size = (UInt32)rem; | 941 | size = (UInt32)rem; |
| 933 | memset(data, 0, size); | 942 | memset(data, 0, size); |
| @@ -965,6 +974,8 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) | |||
| 965 | 974 | ||
| 966 | if (item.Is_Sparse()) | 975 | if (item.Is_Sparse()) |
| 967 | { | 976 | { |
| 977 | if (item.Method_Error) | ||
| 978 | return E_NOTIMPL; // S_FALSE | ||
| 968 | CSparseStream *streamSpec = new CSparseStream; | 979 | CSparseStream *streamSpec = new CSparseStream; |
| 969 | CMyComPtr<IInStream> streamTemp = streamSpec; | 980 | CMyComPtr<IInStream> streamTemp = streamSpec; |
| 970 | streamSpec->Init(); | 981 | streamSpec->Init(); |
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp index 22b8902..e702b68 100644 --- a/CPP/7zip/Archive/Tar/TarIn.cpp +++ b/CPP/7zip/Archive/Tar/TarIn.cpp | |||
| @@ -181,6 +181,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 181 | { | 181 | { |
| 182 | char buf[NFileHeader::kRecordSize]; | 182 | char buf[NFileHeader::kRecordSize]; |
| 183 | 183 | ||
| 184 | item.Method_Error = false; | ||
| 184 | error = k_ErrorType_OK; | 185 | error = k_ErrorType_OK; |
| 185 | filled = false; | 186 | filled = false; |
| 186 | 187 | ||
| @@ -218,10 +219,7 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 218 | break; | 219 | break; |
| 219 | item.HeaderSize += NFileHeader::kRecordSize; | 220 | item.HeaderSize += NFileHeader::kRecordSize; |
| 220 | thereAreEmptyRecords = true; | 221 | thereAreEmptyRecords = true; |
| 221 | if (OpenCallback) | 222 | RINOK(Progress(item, 0)) |
| 222 | { | ||
| 223 | RINOK(Progress(item, 0)) | ||
| 224 | } | ||
| 225 | } | 223 | } |
| 226 | if (thereAreEmptyRecords) | 224 | if (thereAreEmptyRecords) |
| 227 | { | 225 | { |
| @@ -335,84 +333,83 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 335 | 333 | ||
| 336 | if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) | 334 | if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse) |
| 337 | { | 335 | { |
| 338 | Byte isExtended = (Byte)buf[482]; | 336 | // OLD GNU format: parse sparse file information: |
| 339 | if (isExtended != 0 && isExtended != 1) | 337 | // PackSize = cumulative size of all non-empty blocks of the file. |
| 340 | return S_OK; | 338 | // We read actual file size from 'realsize' member of oldgnu_header: |
| 341 | RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin)) | 339 | RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin)) |
| 342 | UInt64 min = 0; | 340 | if (item.Size < item.PackSize) // additional check |
| 343 | for (unsigned i = 0; i < 4; i++) | ||
| 344 | { | ||
| 345 | p = buf + 386 + 24 * i; | ||
| 346 | if (GetBe32(p) == 0) | ||
| 347 | { | ||
| 348 | if (isExtended != 0) | ||
| 349 | return S_OK; | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | CSparseBlock sb; | ||
| 353 | RIF(ParseSize(p, sb.Offset)) | ||
| 354 | RIF(ParseSize(p + 12, sb.Size)) | ||
| 355 | item.SparseBlocks.Add(sb); | ||
| 356 | if (sb.Offset < min || sb.Offset > item.Size) | ||
| 357 | return S_OK; | ||
| 358 | if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) | ||
| 359 | return S_OK; | ||
| 360 | min = sb.Offset + sb.Size; | ||
| 361 | if (min < sb.Offset) | ||
| 362 | return S_OK; | ||
| 363 | } | ||
| 364 | if (min > item.Size) | ||
| 365 | return S_OK; | 341 | return S_OK; |
| 366 | 342 | ||
| 367 | while (isExtended != 0) | 343 | p = buf + 386; |
| 368 | { | 344 | |
| 369 | size_t processedSize = NFileHeader::kRecordSize; | 345 | UInt64 end = 0, packSum = 0; |
| 370 | RINOK(ReadStream(SeqStream, buf, &processedSize)) | 346 | unsigned numRecords = 4; |
| 371 | if (processedSize != NFileHeader::kRecordSize) | 347 | unsigned isExtended = (Byte)p[4 * 24]; // (Byte)p[numRecords * 24]; |
| 372 | { | 348 | // the list of blocks contains non-empty blocks. All another data is empty. |
| 373 | error = k_ErrorType_UnexpectedEnd; | ||
| 374 | return S_OK; | ||
| 375 | } | ||
| 376 | |||
| 377 | item.HeaderSize += NFileHeader::kRecordSize; | ||
| 378 | |||
| 379 | if (OpenCallback) | ||
| 380 | { | ||
| 381 | RINOK(Progress(item, 0)) | ||
| 382 | } | ||
| 383 | 349 | ||
| 384 | isExtended = (Byte)buf[21 * 24]; | 350 | for (;;) |
| 385 | if (isExtended != 0 && isExtended != 1) | 351 | { |
| 352 | // const unsigned isExtended = (Byte)p[numRecords * 24]; | ||
| 353 | if (isExtended > 1) | ||
| 386 | return S_OK; | 354 | return S_OK; |
| 387 | for (unsigned i = 0; i < 21; i++) | 355 | do |
| 388 | { | 356 | { |
| 389 | p = buf + 24 * i; | ||
| 390 | if (GetBe32(p) == 0) | 357 | if (GetBe32(p) == 0) |
| 391 | { | 358 | { |
| 392 | if (isExtended != 0) | 359 | if (isExtended) |
| 393 | return S_OK; | 360 | return S_OK; |
| 394 | break; | 361 | break; |
| 395 | } | 362 | } |
| 396 | CSparseBlock sb; | 363 | CSparseBlock sb; |
| 397 | RIF(ParseSize(p, sb.Offset)) | 364 | RIF(ParseSize(p, sb.Offset)) |
| 398 | RIF(ParseSize(p + 12, sb.Size)) | 365 | RIF(ParseSize(p + 12, sb.Size)) |
| 399 | item.SparseBlocks.Add(sb); | 366 | p += 24; |
| 400 | if (sb.Offset < min || sb.Offset > item.Size) | 367 | /* for all non-last blocks we expect : |
| 401 | return S_OK; | 368 | ((sb.Size & 0x1ff) == 0) && ((sb.Offset & 0x1ff) == 0) |
| 402 | if ((sb.Offset & 0x1FF) != 0 || (sb.Size & 0x1FF) != 0) | 369 | for last block : (sb.Size == 0) is possible. |
| 403 | return S_OK; | 370 | */ |
| 404 | min = sb.Offset + sb.Size; | 371 | if (sb.Offset < end |
| 405 | if (min < sb.Offset) | 372 | || item.Size < sb.Offset |
| 373 | || item.Size - sb.Offset < sb.Size) | ||
| 406 | return S_OK; | 374 | return S_OK; |
| 375 | // optional check: | ||
| 376 | if (sb.Size && ((end & 0x1ff) || (sb.Offset & 0x1ff))) | ||
| 377 | { | ||
| 378 | item.Method_Error = true; // relaxed check | ||
| 379 | // return S_OK; | ||
| 380 | } | ||
| 381 | end = sb.Offset + sb.Size; | ||
| 382 | packSum += sb.Size; | ||
| 383 | item.SparseBlocks.Add(sb); | ||
| 384 | } | ||
| 385 | while (--numRecords); | ||
| 386 | |||
| 387 | if (!isExtended) | ||
| 388 | break; | ||
| 389 | |||
| 390 | size_t processedSize = NFileHeader::kRecordSize; | ||
| 391 | RINOK(ReadStream(SeqStream, buf, &processedSize)) | ||
| 392 | if (processedSize != NFileHeader::kRecordSize) | ||
| 393 | { | ||
| 394 | error = k_ErrorType_UnexpectedEnd; | ||
| 395 | return S_OK; | ||
| 407 | } | 396 | } |
| 397 | item.HeaderSize += NFileHeader::kRecordSize; | ||
| 398 | RINOK(Progress(item, 0)) | ||
| 399 | p = buf; | ||
| 400 | numRecords = 21; | ||
| 401 | isExtended = (Byte)p[21 * 24]; // (Byte)p[numRecords * 24]; | ||
| 402 | } | ||
| 403 | // optional checks for strict size consistency: | ||
| 404 | if (end != item.Size || packSum != item.PackSize) | ||
| 405 | { | ||
| 406 | item.Method_Error = true; // relaxed check | ||
| 407 | // return S_OK; | ||
| 408 | } | 408 | } |
| 409 | if (min > item.Size) | ||
| 410 | return S_OK; | ||
| 411 | } | 409 | } |
| 412 | 410 | ||
| 413 | if (item.PackSize >= (UInt64)1 << 63) | 411 | if (item.PackSize >= (UInt64)1 << 63) // optional check. It was checked in ParseSize() already |
| 414 | return S_OK; | 412 | return S_OK; |
| 415 | |||
| 416 | filled = true; | 413 | filled = true; |
| 417 | error = k_ErrorType_OK; | 414 | error = k_ErrorType_OK; |
| 418 | return S_OK; | 415 | return S_OK; |
| @@ -421,6 +418,8 @@ HRESULT CArchive::GetNextItemReal(CItemEx &item) | |||
| 421 | 418 | ||
| 422 | HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset) | 419 | HRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset) |
| 423 | { | 420 | { |
| 421 | if (!OpenCallback) | ||
| 422 | return S_OK; | ||
| 424 | const UInt64 pos = item.Get_DataPos() + posOffset; | 423 | const UInt64 pos = item.Get_DataPos() + posOffset; |
| 425 | if (NumFiles - NumFiles_Prev < (1 << 16) | 424 | if (NumFiles - NumFiles_Prev < (1 << 16) |
| 426 | // && NumRecords - NumRecords_Prev < (1 << 16) | 425 | // && NumRecords - NumRecords_Prev < (1 << 16) |
| @@ -500,10 +499,7 @@ HRESULT CArchive::ReadDataToBuffer(const CItemEx &item, | |||
| 500 | 499 | ||
| 501 | do | 500 | do |
| 502 | { | 501 | { |
| 503 | if (OpenCallback) | 502 | RINOK(Progress(item, pos)) |
| 504 | { | ||
| 505 | RINOK(Progress(item, pos)) | ||
| 506 | } | ||
| 507 | 503 | ||
| 508 | unsigned size = kBufSize; | 504 | unsigned size = kBufSize; |
| 509 | if (size > packSize) | 505 | if (size > packSize) |
| @@ -813,6 +809,7 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 813 | item.LongLink_WasUsed_2 = false; | 809 | item.LongLink_WasUsed_2 = false; |
| 814 | 810 | ||
| 815 | item.HeaderError = false; | 811 | item.HeaderError = false; |
| 812 | item.Method_Error = false; | ||
| 816 | item.IsSignedChecksum = false; | 813 | item.IsSignedChecksum = false; |
| 817 | item.Prefix_WasUsed = false; | 814 | item.Prefix_WasUsed = false; |
| 818 | 815 | ||
| @@ -838,13 +835,8 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 838 | 835 | ||
| 839 | for (;;) | 836 | for (;;) |
| 840 | { | 837 | { |
| 841 | if (OpenCallback) | 838 | RINOK(Progress(item, 0)) |
| 842 | { | ||
| 843 | RINOK(Progress(item, 0)) | ||
| 844 | } | ||
| 845 | |||
| 846 | RINOK(GetNextItemReal(item)) | 839 | RINOK(GetNextItemReal(item)) |
| 847 | |||
| 848 | // NumRecords++; | 840 | // NumRecords++; |
| 849 | 841 | ||
| 850 | if (!filled) | 842 | if (!filled) |
| @@ -1064,9 +1056,14 @@ HRESULT CArchive::ReadItem2(CItemEx &item) | |||
| 1064 | // GNU TAR ignores (item.Size) in that case | 1056 | // GNU TAR ignores (item.Size) in that case |
| 1065 | if (item.Size != 0 && item.Size != piSize) | 1057 | if (item.Size != 0 && item.Size != piSize) |
| 1066 | item.Pax_Error = true; | 1058 | item.Pax_Error = true; |
| 1067 | item.Size = piSize; | 1059 | if (piSize >= ((UInt64)1 << 63)) |
| 1068 | item.PackSize = piSize; | 1060 | item.Pax_Error = true; |
| 1069 | item.pax_size_WasUsed = true; | 1061 | else |
| 1062 | { | ||
| 1063 | item.Size = piSize; | ||
| 1064 | item.PackSize = piSize; | ||
| 1065 | item.pax_size_WasUsed = true; | ||
| 1066 | } | ||
| 1070 | } | 1067 | } |
| 1071 | 1068 | ||
| 1072 | item.PaxTimes = paxInfo; | 1069 | item.PaxTimes = paxInfo; |
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h index 112f38d..d4e2ea5 100644 --- a/CPP/7zip/Archive/Tar/TarItem.h +++ b/CPP/7zip/Archive/Tar/TarItem.h | |||
| @@ -322,6 +322,7 @@ struct CPaxExtra | |||
| 322 | struct CItemEx: public CItem | 322 | struct CItemEx: public CItem |
| 323 | { | 323 | { |
| 324 | bool HeaderError; | 324 | bool HeaderError; |
| 325 | bool Method_Error; | ||
| 325 | 326 | ||
| 326 | bool IsSignedChecksum; | 327 | bool IsSignedChecksum; |
| 327 | bool Prefix_WasUsed; | 328 | bool Prefix_WasUsed; |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.cpp b/CPP/7zip/Archive/Udf/UdfIn.cpp index ce87c54..a9e4ebf 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.cpp +++ b/CPP/7zip/Archive/Udf/UdfIn.cpp | |||
| @@ -500,10 +500,15 @@ size_t CFileId::Parse(const Byte *p, size_t size) | |||
| 500 | processed += impLen; | 500 | processed += impLen; |
| 501 | Id.Parse(p + processed, idLen); | 501 | Id.Parse(p + processed, idLen); |
| 502 | processed += idLen; | 502 | processed += idLen; |
| 503 | // const size_t processed2 = processed; | ||
| 503 | for (;(processed & 3) != 0; processed++) | 504 | for (;(processed & 3) != 0; processed++) |
| 504 | if (p[processed] != 0) | 505 | if (p[processed] != 0) |
| 505 | return 0; | 506 | return 0; |
| 506 | if ((size_t)tag.CrcLen + 16 != processed) return 0; | 507 | // some program can create non-standard UDF file where CrcLen doesn't include Padding data |
| 508 | if ((size_t)tag.CrcLen + 16 != processed | ||
| 509 | // && (size_t)tag.CrcLen + 16 != processed2 // we can enable this check to support non-standard UDF | ||
| 510 | ) | ||
| 511 | return 0; | ||
| 507 | return (processed <= size) ? processed : 0; | 512 | return (processed <= size) ? processed : 0; |
| 508 | } | 513 | } |
| 509 | 514 | ||
| @@ -577,15 +582,20 @@ HRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDes | |||
| 577 | 582 | ||
| 578 | item.IcbTag.Parse(p + 16); | 583 | item.IcbTag.Parse(p + 16); |
| 579 | 584 | ||
| 585 | // maybe another FileType values are possible in rare cases. | ||
| 586 | // Shoud we ignore FileType here? | ||
| 580 | if (fsIndex < 0) | 587 | if (fsIndex < 0) |
| 581 | { | 588 | { |
| 589 | // if (item.IcbTag.FileType == ICB_FILE_TYPE_DIR) return S_FALSE; | ||
| 582 | if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA && | 590 | if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA && |
| 583 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR) | 591 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR && |
| 592 | item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_BITMAP) | ||
| 584 | return S_FALSE; | 593 | return S_FALSE; |
| 585 | } | 594 | } |
| 586 | else if ( | 595 | else if ( |
| 587 | item.IcbTag.FileType != ICB_FILE_TYPE_DIR && | 596 | item.IcbTag.FileType != ICB_FILE_TYPE_DIR && |
| 588 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE) | 597 | item.IcbTag.FileType != ICB_FILE_TYPE_FILE && |
| 598 | item.IcbTag.FileType != ICB_FILE_TYPE_REAL_TIME_FILE) // M2TS files in /BDMV/STREAM/ in Blu-ray movie | ||
| 589 | return S_FALSE; | 599 | return S_FALSE; |
| 590 | 600 | ||
| 591 | item.Parse(p); | 601 | item.Parse(p); |
| @@ -1210,7 +1220,7 @@ HRESULT CInArchive::Open2() | |||
| 1210 | if (tag.Id != DESC_TYPE_FileSet) | 1220 | if (tag.Id != DESC_TYPE_FileSet) |
| 1211 | return S_FALSE; | 1221 | return S_FALSE; |
| 1212 | 1222 | ||
| 1213 | PRF(printf("\n FileSet", volIndex)); | 1223 | PRF(printf("\n FileSet")); |
| 1214 | CFileSet fs; | 1224 | CFileSet fs; |
| 1215 | fs.RecordingTime.Parse(p + 16); | 1225 | fs.RecordingTime.Parse(p + 16); |
| 1216 | // fs.InterchangeLevel = Get16(p + 18); | 1226 | // fs.InterchangeLevel = Get16(p + 18); |
diff --git a/CPP/7zip/Archive/Udf/UdfIn.h b/CPP/7zip/Archive/Udf/UdfIn.h index 9ccbf74..cbe1a27 100644 --- a/CPP/7zip/Archive/Udf/UdfIn.h +++ b/CPP/7zip/Archive/Udf/UdfIn.h | |||
| @@ -250,9 +250,10 @@ enum EIcbFileType | |||
| 250 | { | 250 | { |
| 251 | ICB_FILE_TYPE_DIR = 4, | 251 | ICB_FILE_TYPE_DIR = 4, |
| 252 | ICB_FILE_TYPE_FILE = 5, | 252 | ICB_FILE_TYPE_FILE = 5, |
| 253 | 253 | ICB_FILE_TYPE_REAL_TIME_FILE = 249, // 2.3.5.2.1 | |
| 254 | ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 Metadata File | 254 | ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 |
| 255 | ICB_FILE_TYPE_METADATA_MIRROR = 251 | 255 | ICB_FILE_TYPE_METADATA_MIRROR = 251, // 2.2.13.1 |
| 256 | ICB_FILE_TYPE_METADATA_BITMAP = 252 // 2.2.13.2 | ||
| 256 | }; | 257 | }; |
| 257 | 258 | ||
| 258 | enum EIcbDescriptorType | 259 | enum EIcbDescriptorType |
diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp index 788810f..9d77e87 100644 --- a/CPP/7zip/Archive/Zip/ZipIn.cpp +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp | |||
| @@ -1718,61 +1718,49 @@ HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) | |||
| 1718 | 1718 | ||
| 1719 | HRESULT CInArchive::FindCd(bool checkOffsetMode) | 1719 | HRESULT CInArchive::FindCd(bool checkOffsetMode) |
| 1720 | { | 1720 | { |
| 1721 | CCdInfo &cdInfo = Vols.ecd; | ||
| 1722 | |||
| 1723 | UInt64 endPos; | ||
| 1724 | |||
| 1725 | // There are no useful data in cache in most cases here. | 1721 | // There are no useful data in cache in most cases here. |
| 1726 | // So here we don't use cache data from previous operations . | 1722 | // So here we don't use cache data from previous operations. |
| 1727 | |||
| 1728 | InitBuf(); | 1723 | InitBuf(); |
| 1724 | UInt64 endPos; | ||
| 1729 | RINOK(InStream_GetSize_SeekToEnd(Stream, endPos)) | 1725 | RINOK(InStream_GetSize_SeekToEnd(Stream, endPos)) |
| 1730 | _streamPos = endPos; | 1726 | _streamPos = endPos; |
| 1731 | 1727 | const size_t kBufSizeMax = (size_t)1 << 17; // must be larger than | |
| 1732 | // const UInt32 kBufSizeMax2 = ((UInt32)1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize; | 1728 | // (1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize |
| 1733 | const size_t kBufSizeMax = ((size_t)1 << 17); // must be larger than kBufSizeMax2 | ||
| 1734 | |||
| 1735 | const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax; | 1729 | const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax; |
| 1736 | if (bufSize < kEcdSize) | 1730 | if (bufSize < kEcdSize) |
| 1737 | return S_FALSE; | 1731 | return S_FALSE; |
| 1738 | // CByteArr byteBuffer(bufSize); | ||
| 1739 | |||
| 1740 | RINOK(AllocateBuffer(kBufSizeMax)) | 1732 | RINOK(AllocateBuffer(kBufSizeMax)) |
| 1733 | { | ||
| 1734 | RINOK(Seek_SavePos(endPos - bufSize)) | ||
| 1735 | size_t processed = bufSize; | ||
| 1736 | const HRESULT res = ReadStream(Stream, Buffer, &processed); | ||
| 1737 | _streamPos += processed; | ||
| 1738 | _bufCached = processed; | ||
| 1739 | _bufPos = 0; | ||
| 1740 | _cnt += processed; | ||
| 1741 | if (res != S_OK) | ||
| 1742 | return res; | ||
| 1743 | if (processed != bufSize) | ||
| 1744 | return S_FALSE; | ||
| 1745 | } | ||
| 1741 | 1746 | ||
| 1742 | RINOK(Seek_SavePos(endPos - bufSize)) | 1747 | CCdInfo &cdInfo = Vols.ecd; |
| 1743 | |||
| 1744 | size_t processed = bufSize; | ||
| 1745 | HRESULT res = ReadStream(Stream, Buffer, &processed); | ||
| 1746 | _streamPos += processed; | ||
| 1747 | _bufCached = processed; | ||
| 1748 | _bufPos = 0; | ||
| 1749 | _cnt += processed; | ||
| 1750 | if (res != S_OK) | ||
| 1751 | return res; | ||
| 1752 | if (processed != bufSize) | ||
| 1753 | return S_FALSE; | ||
| 1754 | |||
| 1755 | 1748 | ||
| 1756 | for (size_t i = bufSize - kEcdSize + 1;;) | 1749 | for (size_t i = bufSize - kEcdSize + 1;;) |
| 1757 | { | 1750 | { |
| 1758 | if (i == 0) | ||
| 1759 | return S_FALSE; | ||
| 1760 | |||
| 1761 | const Byte *buf = Buffer; | 1751 | const Byte *buf = Buffer; |
| 1762 | |||
| 1763 | for (;;) | ||
| 1764 | { | 1752 | { |
| 1765 | i--; | 1753 | const Byte *p = buf + i; |
| 1766 | if (buf[i] == 0x50) | 1754 | do |
| 1767 | break; | 1755 | if (p == buf) |
| 1768 | if (i == 0) | 1756 | return S_FALSE; |
| 1769 | return S_FALSE; | 1757 | while (*(--p) != 0x50); |
| 1770 | } | ||
| 1771 | |||
| 1772 | if (Get32(buf + i) != NSignature::kEcd) | ||
| 1773 | continue; | ||
| 1774 | 1758 | ||
| 1775 | cdInfo.ParseEcd32(buf + i); | 1759 | i = (size_t)(p - buf); |
| 1760 | if (Get32(p) != NSignature::kEcd) | ||
| 1761 | continue; | ||
| 1762 | cdInfo.ParseEcd32(p); | ||
| 1763 | } | ||
| 1776 | 1764 | ||
| 1777 | if (i >= kEcd64Locator_Size) | 1765 | if (i >= kEcd64Locator_Size) |
| 1778 | { | 1766 | { |
| @@ -1793,29 +1781,24 @@ HRESULT CInArchive::FindCd(bool checkOffsetMode) | |||
| 1793 | 1781 | ||
| 1794 | // Most of the zip64 use fixed size Zip64 ECD | 1782 | // Most of the zip64 use fixed size Zip64 ECD |
| 1795 | // we try relative backward reading. | 1783 | // we try relative backward reading. |
| 1796 | 1784 | const UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); | |
| 1797 | UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize); | ||
| 1798 | 1785 | ||
| 1799 | if (locatorIndex >= kEcd64_FullSize) | 1786 | if (locatorIndex >= kEcd64_FullSize) |
| 1800 | if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) | 1787 | if (checkOffsetMode || absEcd64 == locator.Ecd64Offset) |
| 1801 | { | 1788 | { |
| 1802 | const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize; | 1789 | const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize; |
| 1803 | if (Get32(ecd64) == NSignature::kEcd64) | 1790 | if (Get32(ecd64) == NSignature::kEcd64 && |
| 1791 | Get64(ecd64 + 4) == kEcd64_MainSize) | ||
| 1804 | { | 1792 | { |
| 1805 | UInt64 mainEcd64Size = Get64(ecd64 + 4); | 1793 | cdInfo.ParseEcd64e(ecd64 + 12); |
| 1806 | if (mainEcd64Size == kEcd64_MainSize) | 1794 | ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); |
| 1807 | { | 1795 | // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; |
| 1808 | cdInfo.ParseEcd64e(ecd64 + 12); | 1796 | return S_OK; |
| 1809 | ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset); | ||
| 1810 | // ArcInfo.BaseVolIndex = cdInfo.ThisDisk; | ||
| 1811 | return S_OK; | ||
| 1812 | } | ||
| 1813 | } | 1797 | } |
| 1814 | } | 1798 | } |
| 1815 | 1799 | ||
| 1816 | // some zip64 use variable size Zip64 ECD. | 1800 | // some zip64 use variable size Zip64 ECD. |
| 1817 | // we try to use absolute offset from locator. | 1801 | // we try to use absolute offset from locator. |
| 1818 | |||
| 1819 | if (absEcd64 != locator.Ecd64Offset) | 1802 | if (absEcd64 != locator.Ecd64Offset) |
| 1820 | { | 1803 | { |
| 1821 | if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK) | 1804 | if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK) |
| @@ -1881,6 +1864,9 @@ HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdIn | |||
| 1881 | items.Clear(); | 1864 | items.Clear(); |
| 1882 | IsCdUnsorted = false; | 1865 | IsCdUnsorted = false; |
| 1883 | 1866 | ||
| 1867 | if ((Int64)cdOffset < 0) | ||
| 1868 | return S_FALSE; | ||
| 1869 | |||
| 1884 | // _startLocalFromCd_Disk = (UInt32)(Int32)-1; | 1870 | // _startLocalFromCd_Disk = (UInt32)(Int32)-1; |
| 1885 | // _startLocalFromCd_Offset = (UInt64)(Int64)-1; | 1871 | // _startLocalFromCd_Offset = (UInt64)(Int64)-1; |
| 1886 | 1872 | ||
diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp index 63f1a71..e8a21c2 100644 --- a/CPP/7zip/Archive/Zip/ZipOut.cpp +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp | |||
| @@ -49,42 +49,54 @@ void COutArchive::SeekToCurPos() | |||
| 49 | // #define DOES_NEED_ZIP64(v) (v >= 0) | 49 | // #define DOES_NEED_ZIP64(v) (v >= 0) |
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | Z7_NO_INLINE | ||
| 52 | void COutArchive::WriteBytes(const void *data, size_t size) | 53 | void COutArchive::WriteBytes(const void *data, size_t size) |
| 53 | { | 54 | { |
| 54 | m_OutBuffer.WriteBytes(data, size); | 55 | m_OutBuffer.WriteBytes(data, size); |
| 55 | m_CurPos += size; | 56 | m_CurPos += size; |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 59 | Z7_NO_INLINE | ||
| 58 | void COutArchive::Write8(Byte b) | 60 | void COutArchive::Write8(Byte b) |
| 59 | { | 61 | { |
| 60 | m_OutBuffer.WriteByte(b); | 62 | m_OutBuffer.WriteByte(b); |
| 61 | m_CurPos++; | 63 | m_CurPos++; |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 66 | Z7_NO_INLINE | ||
| 64 | void COutArchive::Write16(UInt16 val) | 67 | void COutArchive::Write16(UInt16 val) |
| 65 | { | 68 | { |
| 66 | Write8((Byte)val); | 69 | Write8((Byte)val); |
| 67 | Write8((Byte)(val >> 8)); | 70 | Write8((Byte)(val >> 8)); |
| 68 | } | 71 | } |
| 69 | 72 | ||
| 73 | Z7_NO_INLINE | ||
| 70 | void COutArchive::Write32(UInt32 val) | 74 | void COutArchive::Write32(UInt32 val) |
| 71 | { | 75 | { |
| 72 | for (int i = 0; i < 4; i++) | 76 | for (int i = 0; i < 4; i++) |
| 73 | { | 77 | { |
| 74 | Write8((Byte)val); | 78 | // Write8((Byte)val); |
| 79 | m_OutBuffer.WriteByte((Byte)val); | ||
| 75 | val >>= 8; | 80 | val >>= 8; |
| 76 | } | 81 | } |
| 82 | m_CurPos += 4; | ||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 85 | #define WRITE_CONST_PAIR_16_16(a, b) { Write32((a) | ((UInt32)(b) << 16)); } | ||
| 86 | |||
| 87 | Z7_NO_INLINE | ||
| 79 | void COutArchive::Write64(UInt64 val) | 88 | void COutArchive::Write64(UInt64 val) |
| 80 | { | 89 | { |
| 81 | for (int i = 0; i < 8; i++) | 90 | for (int i = 0; i < 8; i++) |
| 82 | { | 91 | { |
| 83 | Write8((Byte)val); | 92 | // Write8((Byte)val); |
| 93 | m_OutBuffer.WriteByte((Byte)val); | ||
| 84 | val >>= 8; | 94 | val >>= 8; |
| 85 | } | 95 | } |
| 96 | m_CurPos += 8; | ||
| 86 | } | 97 | } |
| 87 | 98 | ||
| 99 | Z7_NO_INLINE | ||
| 88 | void COutArchive::WriteExtra(const CExtraBlock &extra) | 100 | void COutArchive::WriteExtra(const CExtraBlock &extra) |
| 89 | { | 101 | { |
| 90 | FOR_VECTOR (i, extra.SubBlocks) | 102 | FOR_VECTOR (i, extra.SubBlocks) |
| @@ -134,11 +146,9 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs) | |||
| 134 | if (writeNtfs) | 146 | if (writeNtfs) |
| 135 | { | 147 | { |
| 136 | // windows explorer ignores that extra | 148 | // windows explorer ignores that extra |
| 137 | Write16(NFileHeader::NExtraID::kNTFS); | 149 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kNTFS, k_Ntfs_ExtraSize) |
| 138 | Write16(k_Ntfs_ExtraSize); | ||
| 139 | Write32(0); // reserved | 150 | Write32(0); // reserved |
| 140 | Write16(NFileHeader::NNtfsExtra::kTagTime); | 151 | WRITE_CONST_PAIR_16_16(NFileHeader::NNtfsExtra::kTagTime, 8 * 3) |
| 141 | Write16(8 * 3); | ||
| 142 | WriteNtfsTime(item.Ntfs_MTime); | 152 | WriteNtfsTime(item.Ntfs_MTime); |
| 143 | WriteNtfsTime(item.Ntfs_ATime); | 153 | WriteNtfsTime(item.Ntfs_ATime); |
| 144 | WriteNtfsTime(item.Ntfs_CTime); | 154 | WriteNtfsTime(item.Ntfs_CTime); |
| @@ -148,8 +158,7 @@ void COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs) | |||
| 148 | { | 158 | { |
| 149 | // windows explorer ignores that extra | 159 | // windows explorer ignores that extra |
| 150 | // by specification : should we write to local header also? | 160 | // by specification : should we write to local header also? |
| 151 | Write16(NFileHeader::NExtraID::kUnixTime); | 161 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kUnixTime, k_UnixTime_ExtraSize) |
| 152 | Write16(k_UnixTime_ExtraSize); | ||
| 153 | const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime); | 162 | const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime); |
| 154 | Write8(flags); | 163 | Write8(flags); |
| 155 | UInt32 unixTime; | 164 | UInt32 unixTime; |
| @@ -217,8 +226,7 @@ void COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck) | |||
| 217 | 226 | ||
| 218 | if (isZip64) | 227 | if (isZip64) |
| 219 | { | 228 | { |
| 220 | Write16(NFileHeader::NExtraID::kZip64); | 229 | WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kZip64, 8 + 8) |
| 221 | Write16(8 + 8); | ||
| 222 | Write64(size); | 230 | Write64(size); |
| 223 | Write64(packSize); | 231 | Write64(packSize); |
| 224 | } | 232 | } |
| @@ -357,8 +365,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 357 | const UInt64 cdSize = cd64EndOffset - cdOffset; | 365 | const UInt64 cdSize = cd64EndOffset - cdOffset; |
| 358 | const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); | 366 | const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset); |
| 359 | const bool cdSize64 = DOES_NEED_ZIP64(cdSize); | 367 | const bool cdSize64 = DOES_NEED_ZIP64(cdSize); |
| 360 | const bool items64 = items.Size() >= 0xFFFF; | 368 | const bool need_Items_64 = items.Size() >= 0xFFFF; |
| 361 | const bool isZip64 = (cdOffset64 || cdSize64 || items64); | 369 | const unsigned items16 = (UInt16)(need_Items_64 ? 0xFFFF: items.Size()); |
| 370 | const bool isZip64 = (cdOffset64 || cdSize64 || need_Items_64); | ||
| 362 | 371 | ||
| 363 | // isZip64 = true; // to test Zip64 | 372 | // isZip64 = true; // to test Zip64 |
| 364 | 373 | ||
| @@ -371,8 +380,8 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 371 | // const UInt32 extraSize = 1 << 26; | 380 | // const UInt32 extraSize = 1 << 26; |
| 372 | // Write64(kEcd64_MainSize + extraSize); | 381 | // Write64(kEcd64_MainSize + extraSize); |
| 373 | 382 | ||
| 374 | Write16(45); // made by version | 383 | WRITE_CONST_PAIR_16_16(45, // made by version |
| 375 | Write16(45); // extract version | 384 | 45) // extract version |
| 376 | Write32(0); // ThisDiskNumber | 385 | Write32(0); // ThisDiskNumber |
| 377 | Write32(0); // StartCentralDirectoryDiskNumber | 386 | Write32(0); // StartCentralDirectoryDiskNumber |
| 378 | Write64((UInt64)items.Size()); | 387 | Write64((UInt64)items.Size()); |
| @@ -389,10 +398,9 @@ HRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const | |||
| 389 | } | 398 | } |
| 390 | 399 | ||
| 391 | Write32(NSignature::kEcd); | 400 | Write32(NSignature::kEcd); |
| 392 | Write16(0); // ThisDiskNumber | 401 | WRITE_CONST_PAIR_16_16(0, 0) // ThisDiskNumber, StartCentralDirectoryDiskNumber |
| 393 | Write16(0); // StartCentralDirectoryDiskNumber | 402 | Write16((UInt16)items16); |
| 394 | Write16((UInt16)(items64 ? 0xFFFF: items.Size())); | 403 | Write16((UInt16)items16); |
| 395 | Write16((UInt16)(items64 ? 0xFFFF: items.Size())); | ||
| 396 | 404 | ||
| 397 | WRITE_32_VAL_SPEC(cdSize, cdSize64) | 405 | WRITE_32_VAL_SPEC(cdSize, cdSize64) |
| 398 | WRITE_32_VAL_SPEC(cdOffset, cdOffset64) | 406 | WRITE_32_VAL_SPEC(cdOffset, cdOffset64) |
diff --git a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp index aac4e28..9e2d13d 100644 --- a/CPP/7zip/Bundles/SFXCon/SfxCon.cpp +++ b/CPP/7zip/Bundles/SFXCon/SfxCon.cpp | |||
| @@ -153,7 +153,7 @@ namespace NCommandType | |||
| 153 | }; | 153 | }; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static const char *g_Commands = "txl"; | 156 | static const char * const g_Commands = "txl"; |
| 157 | 157 | ||
| 158 | struct CArchiveCommand | 158 | struct CArchiveCommand |
| 159 | { | 159 | { |
diff --git a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp index 0c09807..d4240d9 100644 --- a/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp +++ b/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp | |||
| @@ -48,72 +48,60 @@ static bool ReadDataString(CFSTR fileName, LPCSTR startID, | |||
| 48 | NIO::CInFile inFile; | 48 | NIO::CInFile inFile; |
| 49 | if (!inFile.Open(fileName)) | 49 | if (!inFile.Open(fileName)) |
| 50 | return false; | 50 | return false; |
| 51 | const size_t kBufferSize = (1 << 12); | 51 | const size_t kBufferSize = 1 << 12; |
| 52 | 52 | ||
| 53 | Byte buffer[kBufferSize]; | 53 | Byte buffer[kBufferSize]; |
| 54 | const unsigned signatureStartSize = MyStringLen(startID); | 54 | const size_t signatureStartSize = MyStringLen(startID + 1); |
| 55 | const unsigned signatureEndSize = MyStringLen(endID); | 55 | const size_t signatureEndSize = MyStringLen(endID + 1); |
| 56 | 56 | ||
| 57 | size_t numBytesPrev = 0; | 57 | size_t numBytesPrev = 0; |
| 58 | bool writeMode = false; | 58 | bool writeMode = false; |
| 59 | UInt64 posTotal = 0; | 59 | UInt32 posTotal = 0; |
| 60 | for (;;) | 60 | for (;;) |
| 61 | { | 61 | { |
| 62 | if (posTotal > (1 << 20)) | ||
| 63 | return (stringResult.IsEmpty()); | ||
| 64 | const size_t numReadBytes = kBufferSize - numBytesPrev; | 62 | const size_t numReadBytes = kBufferSize - numBytesPrev; |
| 65 | size_t processedSize; | 63 | size_t processedSize; |
| 66 | if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) | 64 | if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize)) |
| 67 | return false; | 65 | return false; |
| 68 | if (processedSize == 0) | 66 | if (processedSize == 0) |
| 69 | return true; | 67 | return true; |
| 70 | const size_t numBytesInBuffer = numBytesPrev + processedSize; | 68 | numBytesPrev += processedSize; |
| 71 | UInt32 pos = 0; | 69 | size_t pos = 0; |
| 72 | for (;;) | 70 | for (;;) |
| 73 | { | 71 | { |
| 74 | if (writeMode) | 72 | if (writeMode) |
| 75 | { | 73 | { |
| 76 | if (pos + signatureEndSize > numBytesInBuffer) | 74 | if (pos + signatureEndSize > numBytesPrev) |
| 77 | break; | 75 | break; |
| 78 | if (memcmp(buffer + pos, endID, signatureEndSize) == 0) | 76 | const Byte b = buffer[pos++]; |
| 79 | return true; | ||
| 80 | const Byte b = buffer[pos]; | ||
| 81 | if (b == 0) | 77 | if (b == 0) |
| 82 | return false; | 78 | return false; |
| 79 | if (b == ';' && memcmp(buffer + pos, endID + 1, signatureEndSize) == 0) | ||
| 80 | return true; | ||
| 83 | stringResult += (char)b; | 81 | stringResult += (char)b; |
| 84 | pos++; | ||
| 85 | } | 82 | } |
| 86 | else | 83 | else |
| 87 | { | 84 | { |
| 88 | if (pos + signatureStartSize > numBytesInBuffer) | 85 | if (pos + signatureStartSize > numBytesPrev) |
| 89 | break; | 86 | break; |
| 90 | if (memcmp(buffer + pos, startID, signatureStartSize) == 0) | 87 | const Byte b = buffer[pos++]; |
| 88 | if (b == ';' && memcmp(buffer + pos, startID + 1, signatureStartSize) == 0) | ||
| 91 | { | 89 | { |
| 92 | writeMode = true; | 90 | writeMode = true; |
| 93 | pos += signatureStartSize; | 91 | pos += signatureStartSize; |
| 94 | } | 92 | } |
| 95 | else | ||
| 96 | pos++; | ||
| 97 | } | 93 | } |
| 98 | } | 94 | } |
| 99 | numBytesPrev = numBytesInBuffer - pos; | 95 | posTotal += (UInt32)pos; |
| 100 | posTotal += pos; | 96 | if (posTotal > (1 << 21)) |
| 97 | return stringResult.IsEmpty(); | ||
| 98 | numBytesPrev -= pos; | ||
| 101 | memmove(buffer, buffer + pos, numBytesPrev); | 99 | memmove(buffer, buffer + pos, numBytesPrev); |
| 102 | } | 100 | } |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | static char kStartID[] = { ',','!','@','I','n','s','t','a','l','l','@','!','U','T','F','-','8','!', 0 }; | 103 | static const char * const kStartID = ",!@Install@!UTF-8!"; |
| 106 | static char kEndID[] = { ',','!','@','I','n','s','t','a','l','l','E','n','d','@','!', 0 }; | 104 | static const char * const kEndID = ",!@InstallEnd@!"; |
| 107 | |||
| 108 | static struct CInstallIDInit | ||
| 109 | { | ||
| 110 | CInstallIDInit() | ||
| 111 | { | ||
| 112 | kStartID[0] = ';'; | ||
| 113 | kEndID[0] = ';'; | ||
| 114 | } | ||
| 115 | } g_CInstallIDInit; | ||
| 116 | |||
| 117 | 105 | ||
| 118 | #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) | 106 | #if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE) |
| 119 | #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; | 107 | #define NT_CHECK_FAIL_ACTION ShowErrorMessage(L"Unsupported Windows version"); return 1; |
diff --git a/CPP/7zip/Common/FileStreams.cpp b/CPP/7zip/Common/FileStreams.cpp index f90e280..b7e4fbe 100644 --- a/CPP/7zip/Common/FileStreams.cpp +++ b/CPP/7zip/Common/FileStreams.cpp | |||
| @@ -753,7 +753,7 @@ Z7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value)) | |||
| 753 | { | 753 | { |
| 754 | if (StoreOwnerName) | 754 | if (StoreOwnerName) |
| 755 | { | 755 | { |
| 756 | const uid_t gid = st.st_gid; | 756 | const gid_t gid = st.st_gid; |
| 757 | { | 757 | { |
| 758 | if (!OwnerGroup.IsEmpty() && _gid == gid) | 758 | if (!OwnerGroup.IsEmpty() && _gid == gid) |
| 759 | prop = OwnerGroup; | 759 | prop = OwnerGroup; |
diff --git a/CPP/7zip/Common/FileStreams.h b/CPP/7zip/Common/FileStreams.h index 212d4f0..7f465cf 100644 --- a/CPP/7zip/Common/FileStreams.h +++ b/CPP/7zip/Common/FileStreams.h | |||
| @@ -84,8 +84,8 @@ public: | |||
| 84 | BY_HANDLE_FILE_INFORMATION _info; | 84 | BY_HANDLE_FILE_INFORMATION _info; |
| 85 | #else | 85 | #else |
| 86 | struct stat _info; | 86 | struct stat _info; |
| 87 | UInt32 _uid; | 87 | uid_t _uid; // uid_t can be unsigned or signed int |
| 88 | UInt32 _gid; | 88 | gid_t _gid; |
| 89 | UString OwnerName; | 89 | UString OwnerName; |
| 90 | UString OwnerGroup; | 90 | UString OwnerGroup; |
| 91 | bool StoreOwnerId; | 91 | bool StoreOwnerId; |
diff --git a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp index 7fe18fb..73974e6 100644 --- a/CPP/7zip/UI/Common/ArchiveCommandLine.cpp +++ b/CPP/7zip/UI/Common/ArchiveCommandLine.cpp | |||
| @@ -426,7 +426,7 @@ static NRecursedType::EEnum GetRecursedTypeFromIndex(int index) | |||
| 426 | } | 426 | } |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | static const char *g_Commands = "audtexlbih"; | 429 | static const char * const g_Commands = "audtexlbih"; |
| 430 | 430 | ||
| 431 | static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) | 431 | static bool ParseArchiveCommand(const UString &commandString, CArcCommand &command) |
| 432 | { | 432 | { |
diff --git a/CPP/7zip/UI/Common/ArchiveName.cpp b/CPP/7zip/UI/Common/ArchiveName.cpp index 3c0976d..f859d94 100644 --- a/CPP/7zip/UI/Common/ArchiveName.cpp +++ b/CPP/7zip/UI/Common/ArchiveName.cpp | |||
| @@ -17,14 +17,14 @@ using namespace NWindows; | |||
| 17 | using namespace NFile; | 17 | using namespace NFile; |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | static const char *g_ArcExts = | 20 | static const char * const g_ArcExts = |
| 21 | "7z" | 21 | "7z" |
| 22 | "\0" "zip" | 22 | "\0" "zip" |
| 23 | "\0" "tar" | 23 | "\0" "tar" |
| 24 | "\0" "wim" | 24 | "\0" "wim" |
| 25 | "\0"; | 25 | "\0"; |
| 26 | 26 | ||
| 27 | static const char *g_HashExts = | 27 | static const char * const g_HashExts = |
| 28 | "sha256" | 28 | "sha256" |
| 29 | "\0"; | 29 | "\0"; |
| 30 | 30 | ||
diff --git a/CPP/7zip/UI/Common/Bench.cpp b/CPP/7zip/UI/Common/Bench.cpp index eb24e7f..316c980 100644 --- a/CPP/7zip/UI/Common/Bench.cpp +++ b/CPP/7zip/UI/Common/Bench.cpp | |||
| @@ -3038,7 +3038,7 @@ AString GetProcessThreadsInfo(const NSystem::CProcessAffinity &ti) | |||
| 3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) | 3038 | FOR_VECTOR (i, ti.Groups.GroupSizes) |
| 3039 | { | 3039 | { |
| 3040 | if (i != 0) | 3040 | if (i != 0) |
| 3041 | s.Add_Char(' '); | 3041 | s.Add_Space(); |
| 3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); | 3042 | s.Add_UInt32(ti.Groups.GroupSizes[i]); |
| 3043 | } | 3043 | } |
| 3044 | } | 3044 | } |
| @@ -3773,10 +3773,11 @@ HRESULT Bench( | |||
| 3773 | 3773 | ||
| 3774 | #ifndef Z7_ST | 3774 | #ifndef Z7_ST |
| 3775 | 3775 | ||
| 3776 | if (threadsInfo.Get() && threadsInfo.GetNumProcessThreads() != 0) | 3776 | if (!threadsInfo.Get() |
| 3777 | numCPUs = threadsInfo.GetNumProcessThreads(); | 3777 | || (numCPUs = threadsInfo.GetNumProcessThreads()) == 0) |
| 3778 | else | ||
| 3779 | numCPUs = NSystem::GetNumberOfProcessors(); | 3778 | numCPUs = NSystem::GetNumberOfProcessors(); |
| 3779 | // numCPUs : is number of threads assigned to process with affinity, | ||
| 3780 | // or it's total number of threads in all groups, if IsGroupMode == true, and there is default affinity. | ||
| 3780 | 3781 | ||
| 3781 | #endif | 3782 | #endif |
| 3782 | 3783 | ||
diff --git a/CPP/7zip/UI/Console/List.cpp b/CPP/7zip/UI/Console/List.cpp index 874caef..2d9f5a3 100644 --- a/CPP/7zip/UI/Console/List.cpp +++ b/CPP/7zip/UI/Console/List.cpp | |||
| @@ -201,8 +201,8 @@ static const CFieldInfoInit kStandardFieldTable[] = | |||
| 201 | { kpidPath, "Name", kLeft, kLeft, 2, 24 } | 201 | { kpidPath, "Name", kLeft, kLeft, 2, 24 } |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width | 204 | static const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width |
| 205 | static const char *g_Spaces = | 205 | static const char * const g_Spaces = |
| 206 | " " ; | 206 | " " ; |
| 207 | 207 | ||
| 208 | static void PrintSpaces(unsigned numSpaces) | 208 | static void PrintSpaces(unsigned numSpaces) |
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp index ee98ab4..9f083c5 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog2.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog2.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <windowsx.h> | 9 | #include <windowsx.h> |
| 10 | 10 | ||
| 11 | #include "../../../Common/IntToString.h" | 11 | #include "../../../Common/IntToString.h" |
| 12 | #include "../../../Common/MyCom.h" | ||
| 12 | #include "../../../Common/StringConvert.h" | 13 | #include "../../../Common/StringConvert.h" |
| 13 | #include "../../../Common/Wildcard.h" | 14 | #include "../../../Common/Wildcard.h" |
| 14 | 15 | ||
| @@ -19,6 +20,7 @@ | |||
| 19 | #include "../../../Windows/Menu.h" | 20 | #include "../../../Windows/Menu.h" |
| 20 | #include "../../../Windows/ProcessUtils.h" | 21 | #include "../../../Windows/ProcessUtils.h" |
| 21 | #include "../../../Windows/PropVariantConv.h" | 22 | #include "../../../Windows/PropVariantConv.h" |
| 23 | #include "../../../Windows/Shell.h" | ||
| 22 | #include "../../../Windows/Control/ComboBox.h" | 24 | #include "../../../Windows/Control/ComboBox.h" |
| 23 | #include "../../../Windows/Control/Dialog.h" | 25 | #include "../../../Windows/Control/Dialog.h" |
| 24 | #include "../../../Windows/Control/Edit.h" | 26 | #include "../../../Windows/Control/Edit.h" |
| @@ -57,7 +59,7 @@ static const int kParentIndex = -1; | |||
| 57 | // static const UINT k_Message_RefreshPathEdit = WM_APP + 1; | 59 | // static const UINT k_Message_RefreshPathEdit = WM_APP + 1; |
| 58 | 60 | ||
| 59 | 61 | ||
| 60 | static const wchar_t *k_Message_Link_operation_was_Blocked = | 62 | static const wchar_t * const k_Message_Link_operation_was_Blocked = |
| 61 | L"link openning was blocked by 7-Zip"; | 63 | L"link openning was blocked by 7-Zip"; |
| 62 | 64 | ||
| 63 | extern UString HResultToMessage(HRESULT errorCode); | 65 | extern UString HResultToMessage(HRESULT errorCode); |
| @@ -978,35 +980,61 @@ void CBrowseDialog2::OnHelp() | |||
| 978 | #endif | 980 | #endif |
| 979 | 981 | ||
| 980 | 982 | ||
| 983 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | ||
| 984 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl); | ||
| 985 | |||
| 981 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process); | 986 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process); |
| 982 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process) | 987 | HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process) |
| 983 | { | 988 | { |
| 984 | UString path2 = path; | 989 | UString path2 = path; |
| 985 | 990 | UINT32 result; | |
| 986 | #ifdef _WIN32 | 991 | { |
| 992 | #ifdef _WIN32 | ||
| 993 | NShell::CItemIDList pidl; | ||
| 994 | // SHELLEXECUTEINFO::pidl is more accurate way than SHELLEXECUTEINFO::lpFile | ||
| 995 | { | ||
| 996 | CMyComPtr<IShellFolder> desktop; | ||
| 997 | if (SHGetDesktopFolder(&desktop) == S_OK && desktop) | ||
| 998 | if (ShellFolder_ParseDisplayName(desktop, | ||
| 999 | NULL, // HWND : do we need (window) or NULL here? | ||
| 1000 | path, | ||
| 1001 | &pidl) != S_OK) | ||
| 1002 | pidl.Detach(); | ||
| 1003 | } | ||
| 987 | { | 1004 | { |
| 988 | const int dot = path2.ReverseFind_Dot(); | 1005 | const int dot = path2.ReverseFind_Dot(); |
| 989 | const int separ = path2.ReverseFind_PathSepar(); | 1006 | const int separ = path2.ReverseFind_PathSepar(); |
| 990 | if (dot < 0 || dot < separ) | 1007 | if (separ != (int)path2.Len() - 1) |
| 991 | path2.Add_Dot(); | 1008 | if (dot < 0 || dot < separ) |
| 1009 | path2.Add_Dot(); | ||
| 992 | } | 1010 | } |
| 993 | #endif | 1011 | #endif // _WIN32 |
| 994 | 1012 | ||
| 995 | UINT32 result; | ||
| 996 | |||
| 997 | #ifndef _UNICODE | 1013 | #ifndef _UNICODE |
| 998 | if (g_IsNT) | 1014 | if (g_IsNT) |
| 999 | { | 1015 | { |
| 1000 | SHELLEXECUTEINFOW execInfo; | 1016 | SHELLEXECUTEINFOW execInfo; |
| 1017 | memset(&execInfo, 0, sizeof(execInfo)); | ||
| 1018 | // execInfo.hwnd = NULL; | ||
| 1019 | // execInfo.lpVerb = NULL; | ||
| 1020 | // execInfo.lpFile = NULL; | ||
| 1021 | // execInfo.lpDirectory = NULL; | ||
| 1022 | // execInfo.lpParameters = NULL; | ||
| 1023 | // execInfo.hProcess = NULL; | ||
| 1001 | execInfo.cbSize = sizeof(execInfo); | 1024 | execInfo.cbSize = sizeof(execInfo); |
| 1002 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; | 1025 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT; |
| 1003 | execInfo.hwnd = NULL; | 1026 | if (!dir.IsEmpty()) |
| 1004 | execInfo.lpVerb = NULL; | 1027 | execInfo.lpDirectory = dir; |
| 1005 | execInfo.lpFile = path2; | ||
| 1006 | execInfo.lpParameters = NULL; | ||
| 1007 | execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir; | ||
| 1008 | execInfo.nShow = SW_SHOWNORMAL; | 1028 | execInfo.nShow = SW_SHOWNORMAL; |
| 1009 | execInfo.hProcess = NULL; | 1029 | |
| 1030 | if ((LPCITEMIDLIST)pidl) | ||
| 1031 | { | ||
| 1032 | execInfo.lpIDList = pidl; | ||
| 1033 | execInfo.fMask |= SEE_MASK_IDLIST; | ||
| 1034 | } | ||
| 1035 | else | ||
| 1036 | execInfo.lpFile = path2; | ||
| 1037 | |||
| 1010 | typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo); | 1038 | typedef BOOL (WINAPI * Func_ShellExecuteExW)(LPSHELLEXECUTEINFOW lpExecInfo); |
| 1011 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | 1039 | Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION |
| 1012 | const | 1040 | const |
| @@ -1024,34 +1052,40 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
| 1024 | #endif | 1052 | #endif |
| 1025 | { | 1053 | { |
| 1026 | SHELLEXECUTEINFO execInfo; | 1054 | SHELLEXECUTEINFO execInfo; |
| 1055 | memset(&execInfo, 0, sizeof(execInfo)); | ||
| 1056 | // execInfo.hwnd = NULL; | ||
| 1057 | // execInfo.lpVerb = NULL; | ||
| 1058 | // execInfo.lpFile = NULL; | ||
| 1059 | // execInfo.lpDirectory = NULL; | ||
| 1060 | // execInfo.lpParameters = NULL; | ||
| 1061 | // execInfo.hProcess = NULL; | ||
| 1027 | execInfo.cbSize = sizeof(execInfo); | 1062 | execInfo.cbSize = sizeof(execInfo); |
| 1028 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | 1063 | execInfo.fMask = SEE_MASK_NOCLOSEPROCESS |
| 1029 | #ifndef UNDER_CE | 1064 | #ifndef UNDER_CE |
| 1030 | | SEE_MASK_FLAG_DDEWAIT | 1065 | | SEE_MASK_FLAG_DDEWAIT |
| 1031 | #endif | 1066 | #endif |
| 1032 | ; | 1067 | ; |
| 1033 | execInfo.hwnd = NULL; | 1068 | execInfo.nShow = SW_SHOWNORMAL; |
| 1034 | execInfo.lpVerb = NULL; | ||
| 1035 | const CSysString sysPath (GetSystemString(path2)); | 1069 | const CSysString sysPath (GetSystemString(path2)); |
| 1036 | const CSysString sysDir (GetSystemString(dir)); | 1070 | const CSysString sysDir (GetSystemString(dir)); |
| 1037 | execInfo.lpFile = sysPath; | 1071 | #ifndef UNDER_CE |
| 1038 | execInfo.lpParameters = NULL; | 1072 | if (!sysDir.IsEmpty()) |
| 1039 | execInfo.lpDirectory = | 1073 | execInfo.lpDirectory = sysDir; |
| 1040 | #ifdef UNDER_CE | 1074 | #endif |
| 1041 | NULL | 1075 | |
| 1042 | #else | 1076 | if ((LPCITEMIDLIST)pidl) |
| 1043 | sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir | 1077 | { |
| 1044 | #endif | 1078 | execInfo.lpIDList = pidl; |
| 1045 | ; | 1079 | execInfo.fMask |= SEE_MASK_IDLIST; |
| 1046 | execInfo.nShow = SW_SHOWNORMAL; | 1080 | } |
| 1047 | execInfo.hProcess = NULL; | 1081 | else |
| 1082 | execInfo.lpFile = sysPath; | ||
| 1048 | ::ShellExecuteEx(&execInfo); | 1083 | ::ShellExecuteEx(&execInfo); |
| 1049 | result = (UINT32)(UINT_PTR)execInfo.hInstApp; | 1084 | result = (UINT32)(UINT_PTR)execInfo.hInstApp; |
| 1050 | process.Attach(execInfo.hProcess); | 1085 | process.Attach(execInfo.hProcess); |
| 1051 | } | 1086 | } |
| 1052 | |||
| 1053 | // DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result) | 1087 | // DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result) |
| 1054 | 1088 | } | |
| 1055 | if (result <= 32) | 1089 | if (result <= 32) |
| 1056 | { | 1090 | { |
| 1057 | switch (result) | 1091 | switch (result) |
| @@ -1063,10 +1097,8 @@ Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION | |||
| 1063 | // L"There is no application associated with the given file name extension", | 1097 | // L"There is no application associated with the given file name extension", |
| 1064 | ); | 1098 | ); |
| 1065 | } | 1099 | } |
| 1066 | |||
| 1067 | return E_FAIL; // fixed in 15.13. Can we use it for any Windows version? | 1100 | return E_FAIL; // fixed in 15.13. Can we use it for any Windows version? |
| 1068 | } | 1101 | } |
| 1069 | |||
| 1070 | return S_OK; | 1102 | return S_OK; |
| 1071 | } | 1103 | } |
| 1072 | 1104 | ||
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp index 7956d86..51dfaa9 100644 --- a/CPP/7zip/UI/FileManager/FSFolder.cpp +++ b/CPP/7zip/UI/FileManager/FSFolder.cpp | |||
| @@ -748,8 +748,8 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI | |||
| 748 | case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime); | 748 | case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime); |
| 749 | case kpidIsDir: | 749 | case kpidIsDir: |
| 750 | { | 750 | { |
| 751 | bool isDir1 = /* ss1 ? false : */ fi1.IsDir(); | 751 | const bool isDir1 = /* ss1 ? false : */ fi1.IsDir(); |
| 752 | bool isDir2 = /* ss2 ? false : */ fi2.IsDir(); | 752 | const bool isDir2 = /* ss2 ? false : */ fi2.IsDir(); |
| 753 | if (isDir1 == isDir2) | 753 | if (isDir1 == isDir2) |
| 754 | return 0; | 754 | return 0; |
| 755 | return isDir1 ? -1 : 1; | 755 | return isDir1 ? -1 : 1; |
| @@ -798,7 +798,9 @@ Z7_COM7F_IMF2(Int32, CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPI | |||
| 798 | return MyStringCompareNoCase(comment1, comment2); | 798 | return MyStringCompareNoCase(comment1, comment2); |
| 799 | } | 799 | } |
| 800 | case kpidPrefix: | 800 | case kpidPrefix: |
| 801 | if (fi1.Parent < 0) return (fi2.Parent < 0) ? 0 : -1; | 801 | if (fi1.Parent == fi2.Parent) |
| 802 | return 0; | ||
| 803 | if (fi1.Parent < 0) return -1; | ||
| 802 | if (fi2.Parent < 0) return 1; | 804 | if (fi2.Parent < 0) return 1; |
| 803 | return CompareFileNames_ForFolderList( | 805 | return CompareFileNames_ForFolderList( |
| 804 | Folders[fi1.Parent], | 806 | Folders[fi1.Parent], |
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp index 3aeaf13..626c91b 100644 --- a/CPP/7zip/UI/FileManager/LangPage.cpp +++ b/CPP/7zip/UI/FileManager/LangPage.cpp | |||
| @@ -253,8 +253,7 @@ bool CLangPage::OnInit() | |||
| 253 | temp += " "; | 253 | temp += " "; |
| 254 | temp += rec.Mark; | 254 | temp += rec.Mark; |
| 255 | } | 255 | } |
| 256 | const int index = (int)_langCombo.AddString(temp); | 256 | const int index = (int)_langCombo.AddString_SetItemData(temp, (LPARAM)rec.LangInfoIndex); |
| 257 | _langCombo.SetItemData(index, (LPARAM)rec.LangInfoIndex); | ||
| 258 | if (rec.IsSelected) | 257 | if (rec.IsSelected) |
| 259 | _langCombo.SetCurSel(index); | 258 | _langCombo.SetCurSel(index); |
| 260 | } | 259 | } |
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp index e8736b8..61dd8cb 100644 --- a/CPP/7zip/UI/FileManager/MenuPage.cpp +++ b/CPP/7zip/UI/FileManager/MenuPage.cpp | |||
| @@ -222,8 +222,7 @@ bool CMenuPage::OnInit() | |||
| 222 | s.Add_UInt32(val); | 222 | s.Add_UInt32(val); |
| 223 | if (i == 0) | 223 | if (i == 0) |
| 224 | s.Insert(0, L"* "); | 224 | s.Insert(0, L"* "); |
| 225 | const int index = (int)_zoneCombo.AddString(s); | 225 | const int index = (int)_zoneCombo.AddString_SetItemData(s, (LPARAM)val); |
| 226 | _zoneCombo.SetItemData(index, (LPARAM)val); | ||
| 227 | if (val == wz) | 226 | if (val == wz) |
| 228 | _zoneCombo.SetCurSel(index); | 227 | _zoneCombo.SetCurSel(index); |
| 229 | } | 228 | } |
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp index aa56ef5..9d78368 100644 --- a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp +++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp | |||
| @@ -825,7 +825,10 @@ void CPanel::EditItem(unsigned index, bool useEditor) | |||
| 825 | return; | 825 | return; |
| 826 | } | 826 | } |
| 827 | CProcess process; | 827 | CProcess process; |
| 828 | StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process); | 828 | StartEditApplication(GetItemFullPath(index), useEditor, |
| 829 | // (HWND)*this, | ||
| 830 | GetParent(), | ||
| 831 | process); | ||
| 829 | } | 832 | } |
| 830 | 833 | ||
| 831 | 834 | ||
| @@ -854,7 +857,10 @@ void CPanel::OpenFolderExternal(unsigned index) | |||
| 854 | path.Add_PathSepar(); | 857 | path.Add_PathSepar(); |
| 855 | } | 858 | } |
| 856 | 859 | ||
| 857 | StartApplicationDontWait(prefix, path, (HWND)*this); | 860 | StartApplicationDontWait(prefix, path, |
| 861 | // (HWND)*this | ||
| 862 | GetParent() | ||
| 863 | ); | ||
| 858 | } | 864 | } |
| 859 | 865 | ||
| 860 | 866 | ||
| @@ -981,7 +987,10 @@ void CPanel::OpenItem(unsigned index, bool tryInternal, bool tryExternal, const | |||
| 981 | { | 987 | { |
| 982 | // SetCurrentDirectory opens HANDLE to folder!!! | 988 | // SetCurrentDirectory opens HANDLE to folder!!! |
| 983 | // NDirectory::MySetCurrentDirectory(prefix); | 989 | // NDirectory::MySetCurrentDirectory(prefix); |
| 984 | StartApplicationDontWait(prefix, fullPath, (HWND)*this); | 990 | StartApplicationDontWait(prefix, fullPath, |
| 991 | // (HWND)*this | ||
| 992 | GetParent() | ||
| 993 | ); | ||
| 985 | } | 994 | } |
| 986 | } | 995 | } |
| 987 | 996 | ||
| @@ -1732,9 +1741,15 @@ void CPanel::OpenItemInArchive(unsigned index, bool tryInternal, bool tryExterna | |||
| 1732 | CProcess process; | 1741 | CProcess process; |
| 1733 | HRESULT res; | 1742 | HRESULT res; |
| 1734 | if (editMode) | 1743 | if (editMode) |
| 1735 | res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process); | 1744 | res = StartEditApplication(fs2us(tempFilePath), useEditor, |
| 1745 | // (HWND)*this, | ||
| 1746 | GetParent(), | ||
| 1747 | process); | ||
| 1736 | else | 1748 | else |
| 1737 | res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process); | 1749 | res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), |
| 1750 | // (HWND)*this, | ||
| 1751 | GetParent(), | ||
| 1752 | process); | ||
| 1738 | 1753 | ||
| 1739 | if ((HANDLE)process == NULL) | 1754 | if ((HANDLE)process == NULL) |
| 1740 | { | 1755 | { |
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 9086996..e655843 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp | |||
| @@ -488,7 +488,9 @@ struct CFolderPidls | |||
| 488 | }; | 488 | }; |
| 489 | 489 | ||
| 490 | 490 | ||
| 491 | static HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | 491 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, |
| 492 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl); | ||
| 493 | HRESULT ShellFolder_ParseDisplayName(IShellFolder *shellFolder, | ||
| 492 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) | 494 | HWND hwnd, const UString &path, LPITEMIDLIST *ppidl) |
| 493 | { | 495 | { |
| 494 | ULONG eaten = 0; | 496 | ULONG eaten = 0; |
diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp index f95f8ee..57ac877 100644 --- a/CPP/7zip/UI/FileManager/PanelSort.cpp +++ b/CPP/7zip/UI/FileManager/PanelSort.cpp | |||
| @@ -82,7 +82,7 @@ static inline const wchar_t *GetExtensionPtr(const UString &name) | |||
| 82 | 82 | ||
| 83 | void CPanel::SetSortRawStatus() | 83 | void CPanel::SetSortRawStatus() |
| 84 | { | 84 | { |
| 85 | _isRawSortProp = false; | 85 | _isRawSortProp = 0; // false; |
| 86 | FOR_VECTOR (i, _columns) | 86 | FOR_VECTOR (i, _columns) |
| 87 | { | 87 | { |
| 88 | const CPropColumn &prop = _columns[i]; | 88 | const CPropColumn &prop = _columns[i]; |
| @@ -95,21 +95,15 @@ void CPanel::SetSortRawStatus() | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | 97 | ||
| 98 | static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | 98 | static int CALLBACK CompareItems2(const LPARAM lParam1, const LPARAM lParam2, |
| 99 | const CPanel * const panel, const PROPID propID, const Int32 isRawProp) | ||
| 99 | { | 100 | { |
| 100 | if (lpData == 0) | ||
| 101 | return 0; | ||
| 102 | CPanel *panel = (CPanel*)lpData; | ||
| 103 | |||
| 104 | |||
| 105 | PROPID propID = panel->_sortID; | ||
| 106 | |||
| 107 | if (propID == kpidNoProperty) | 101 | if (propID == kpidNoProperty) |
| 108 | return MyCompare(lParam1, lParam2); | 102 | return MyCompare(lParam1, lParam2); |
| 109 | 103 | ||
| 110 | if (panel->_isRawSortProp) | 104 | if (isRawProp) |
| 111 | { | 105 | { |
| 112 | // Sha1, NtSecurity, NtReparse | 106 | // Sha1, Checksum, NtSecurity, NtReparse |
| 113 | const void *data1; | 107 | const void *data1; |
| 114 | const void *data2; | 108 | const void *data2; |
| 115 | UInt32 dataSize1; | 109 | UInt32 dataSize1; |
| @@ -135,7 +129,7 @@ static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | |||
| 135 | } | 129 | } |
| 136 | 130 | ||
| 137 | if (panel->_folderCompare) | 131 | if (panel->_folderCompare) |
| 138 | return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, panel->_isRawSortProp); | 132 | return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, isRawProp); |
| 139 | 133 | ||
| 140 | switch (propID) | 134 | switch (propID) |
| 141 | { | 135 | { |
| @@ -189,16 +183,41 @@ int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | |||
| 189 | if (lParam1 == (int)kParentIndex) return -1; | 183 | if (lParam1 == (int)kParentIndex) return -1; |
| 190 | if (lParam2 == (int)kParentIndex) return 1; | 184 | if (lParam2 == (int)kParentIndex) return 1; |
| 191 | 185 | ||
| 192 | CPanel *panel = (CPanel*)lpData; | 186 | const CPanel *panel = (CPanel*)lpData; |
| 193 | 187 | ||
| 194 | const bool isDir1 = panel->IsItem_Folder((unsigned)lParam1); | 188 | const bool isDir1 = panel->IsItem_Folder((unsigned)lParam1); |
| 195 | const bool isDir2 = panel->IsItem_Folder((unsigned)lParam2); | 189 | const bool isDir2 = panel->IsItem_Folder((unsigned)lParam2); |
| 196 | 190 | if (isDir1 != isDir2) | |
| 197 | if (isDir1 && !isDir2) return -1; | 191 | return isDir1 ? -1 : 1; |
| 198 | if (isDir2 && !isDir1) return 1; | ||
| 199 | 192 | ||
| 200 | const int result = CompareItems2(lParam1, lParam2, lpData); | 193 | /* |
| 201 | return panel->_ascending ? result: (-result); | 194 | we have up to 3 iterations: |
| 195 | 1: prop, | ||
| 196 | 2: kpidName, kpidPrefix | ||
| 197 | 3: prop, kpidName, kpidPrefix | ||
| 198 | 3: kpidPrefix, kpidName, kpidPrefix : is some rare case | ||
| 199 | */ | ||
| 200 | PROPID propID = panel->_sortID; | ||
| 201 | int res = 0; | ||
| 202 | for (unsigned iter = 0; iter < 3; iter++) | ||
| 203 | { | ||
| 204 | res = CompareItems2(lParam1, lParam2, panel, propID, | ||
| 205 | iter ? 0 : panel->_isRawSortProp); | ||
| 206 | if (res) | ||
| 207 | break; | ||
| 208 | if (propID == kpidName) | ||
| 209 | { | ||
| 210 | // if (!_flatMode.IsEmpty()) break; // !_flatMode ; | ||
| 211 | propID = kpidPrefix; | ||
| 212 | continue; | ||
| 213 | } | ||
| 214 | if (iter) | ||
| 215 | break; | ||
| 216 | propID = kpidName; | ||
| 217 | } | ||
| 218 | if (res == 0) | ||
| 219 | res = MyCompare(lParam1, lParam2); // order of LoadSubItems() | ||
| 220 | return panel->_ascending ? res: -res; | ||
| 202 | } | 221 | } |
| 203 | 222 | ||
| 204 | 223 | ||
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 1686c69..980161f 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp | |||
| @@ -440,11 +440,9 @@ static const size_t kMaxDicSize = (size_t)1 << (22 + sizeof(size_t) / 4 * 5); | |||
| 440 | 440 | ||
| 441 | static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v) | 441 | static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v) |
| 442 | { | 442 | { |
| 443 | TCHAR s[16]; | 443 | WCHAR s[16]; |
| 444 | ConvertUInt32ToString(v, s); | 444 | ConvertUInt32ToString(v, s); |
| 445 | const int index = (int)cb.AddString(s); | 445 | return (int)cb.AddString_SetItemData(s, (LPARAM)v); |
| 446 | cb.SetItemData(index, (LPARAM)v); | ||
| 447 | return index; | ||
| 448 | } | 446 | } |
| 449 | 447 | ||
| 450 | 448 | ||
| @@ -481,21 +479,17 @@ bool CBenchmarkDialog::OnInit() | |||
| 481 | _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); | 479 | _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE); |
| 482 | } | 480 | } |
| 483 | 481 | ||
| 484 | UInt32 numCPUs = 1; | 482 | UInt32 numCPUs = 1; // process threads |
| 483 | UInt32 numCPUs_Sys = 1; // system threads | ||
| 485 | 484 | ||
| 486 | { | 485 | { |
| 487 | AString s ("/ "); | ||
| 488 | |||
| 489 | NSystem::CProcessAffinity threadsInfo; | 486 | NSystem::CProcessAffinity threadsInfo; |
| 490 | threadsInfo.InitST(); | 487 | threadsInfo.InitST(); |
| 488 | #ifndef Z7_ST | ||
| 489 | threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numCPUs_Sys); | ||
| 490 | #endif | ||
| 491 | 491 | ||
| 492 | #ifndef Z7_ST | 492 | AString s ("/ "); |
| 493 | if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0) | ||
| 494 | numCPUs = threadsInfo.GetNumProcessThreads(); | ||
| 495 | else | ||
| 496 | numCPUs = NSystem::GetNumberOfProcessors(); | ||
| 497 | #endif | ||
| 498 | |||
| 499 | s.Add_UInt32(numCPUs); | 493 | s.Add_UInt32(numCPUs); |
| 500 | s += GetProcessThreadsInfo(threadsInfo); | 494 | s += GetProcessThreadsInfo(threadsInfo); |
| 501 | SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s); | 495 | SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s); |
| @@ -506,10 +500,8 @@ bool CBenchmarkDialog::OnInit() | |||
| 506 | SetItemTextA(IDT_BENCH_SYS1, s); | 500 | SetItemTextA(IDT_BENCH_SYS1, s); |
| 507 | if (s != s2 && !s2.IsEmpty()) | 501 | if (s != s2 && !s2.IsEmpty()) |
| 508 | SetItemTextA(IDT_BENCH_SYS2, s2); | 502 | SetItemTextA(IDT_BENCH_SYS2, s2); |
| 509 | } | 503 | |
| 510 | { | 504 | GetCpuName_MultiLine(s, s2); // s2==registers |
| 511 | AString registers; | ||
| 512 | GetCpuName_MultiLine(s, registers); | ||
| 513 | SetItemTextA(IDT_BENCH_CPU, s); | 505 | SetItemTextA(IDT_BENCH_CPU, s); |
| 514 | } | 506 | } |
| 515 | { | 507 | { |
| @@ -526,22 +518,18 @@ bool CBenchmarkDialog::OnInit() | |||
| 526 | 518 | ||
| 527 | // ----- Num Threads ---------- | 519 | // ----- Num Threads ---------- |
| 528 | 520 | ||
| 529 | if (numCPUs < 1) | ||
| 530 | numCPUs = 1; | ||
| 531 | numCPUs = MyMin(numCPUs, (UInt32)(1 << 6)); // it's WIN32 limit | ||
| 532 | |||
| 533 | UInt32 numThreads = Sync.NumThreads; | 521 | UInt32 numThreads = Sync.NumThreads; |
| 534 | |||
| 535 | if (numThreads == (UInt32)(Int32)-1) | 522 | if (numThreads == (UInt32)(Int32)-1) |
| 536 | numThreads = numCPUs; | 523 | numThreads = numCPUs; |
| 537 | if (numThreads > 1) | 524 | numThreads &= ~(UInt32)1; |
| 538 | numThreads &= ~(UInt32)1; | 525 | if (numThreads == 0) |
| 539 | const UInt32 kNumThreadsMax = (1 << 12); | 526 | numThreads = 1; |
| 540 | if (numThreads > kNumThreadsMax) | 527 | numThreads = MyMin(numThreads, (UInt32)(1u << 14)); |
| 541 | numThreads = kNumThreadsMax; | ||
| 542 | 528 | ||
| 543 | m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS)); | 529 | m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS)); |
| 544 | const UInt32 numTheads_Combo = numCPUs * 2; | 530 | if (numCPUs_Sys == 0) |
| 531 | numCPUs_Sys = 1; | ||
| 532 | const UInt32 numTheads_Combo = numCPUs_Sys * 2; | ||
| 545 | UInt32 v = 1; | 533 | UInt32 v = 1; |
| 546 | int cur = 0; | 534 | int cur = 0; |
| 547 | for (; v <= numTheads_Combo;) | 535 | for (; v <= numTheads_Combo;) |
| @@ -1069,16 +1057,17 @@ static void AddUsageString(UString &s, const CTotalBenchRes &info) | |||
| 1069 | numIter = 1000000; | 1057 | numIter = 1000000; |
| 1070 | UInt64 usage = GetUsagePercents(info.Usage / numIter); | 1058 | UInt64 usage = GetUsagePercents(info.Usage / numIter); |
| 1071 | 1059 | ||
| 1072 | wchar_t w[64]; | 1060 | wchar_t w[32]; |
| 1073 | ConvertUInt64ToString(usage, w); | 1061 | wchar_t *p = ConvertUInt64ToString(usage, w); |
| 1074 | unsigned len = MyStringLen(w); | 1062 | p[0] = '%'; |
| 1063 | p[1] = 0; | ||
| 1064 | unsigned len = (unsigned)(size_t)(p - w); | ||
| 1075 | while (len < 5) | 1065 | while (len < 5) |
| 1076 | { | 1066 | { |
| 1077 | s.Add_Space(); | 1067 | s.Add_Space(); |
| 1078 | len++; | 1068 | len++; |
| 1079 | } | 1069 | } |
| 1080 | s += w; | 1070 | s += w; |
| 1081 | s += "%"; | ||
| 1082 | } | 1071 | } |
| 1083 | 1072 | ||
| 1084 | 1073 | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 85d7186..53e56fe 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp | |||
| @@ -506,8 +506,7 @@ bool CCompressDialog::OnInit() | |||
| 506 | { | 506 | { |
| 507 | const unsigned arcIndex = ArcIndices[i]; | 507 | const unsigned arcIndex = ArcIndices[i]; |
| 508 | const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; | 508 | const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; |
| 509 | const int index = (int)m_Format.AddString(ai.Name); | 509 | const int index = (int)m_Format.AddString_SetItemData(ai.Name, (LPARAM)arcIndex); |
| 510 | m_Format.SetItemData(index, (LPARAM)arcIndex); | ||
| 511 | if (!needSetMain) | 510 | if (!needSetMain) |
| 512 | { | 511 | { |
| 513 | if (Info.FormatIndex == (int)arcIndex) | 512 | if (Info.FormatIndex == (int)arcIndex) |
| @@ -540,11 +539,6 @@ bool CCompressDialog::OnInit() | |||
| 540 | AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs), | 539 | AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs), |
| 541 | k_PathMode_Vals, Info.PathMode); | 540 | k_PathMode_Vals, Info.PathMode); |
| 542 | 541 | ||
| 543 | |||
| 544 | TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 }; | ||
| 545 | ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); | ||
| 546 | SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); | ||
| 547 | |||
| 548 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); | 542 | CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); |
| 549 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); | 543 | CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); |
| 550 | 544 | ||
| @@ -653,7 +647,19 @@ void CCompressDialog::EnableMultiCombo(unsigned id) | |||
| 653 | EnableItem(id, enable); | 647 | EnableItem(id, enable); |
| 654 | } | 648 | } |
| 655 | 649 | ||
| 656 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s); | 650 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s) |
| 651 | { | ||
| 652 | return cb.AddString((CSysString)s); | ||
| 653 | } | ||
| 654 | |||
| 655 | static LRESULT ComboBox_AddStringAscii_SetItemData(NControl::CComboBox &cb, | ||
| 656 | const char *s, LPARAM lParam) | ||
| 657 | { | ||
| 658 | const LRESULT index = ComboBox_AddStringAscii(cb, s); | ||
| 659 | if (index >= 0) // optional check | ||
| 660 | cb.SetItemData((int)index, lParam); | ||
| 661 | return index; | ||
| 662 | } | ||
| 657 | 663 | ||
| 658 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) | 664 | static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res) |
| 659 | { | 665 | { |
| @@ -1604,20 +1610,14 @@ void CCompressDialog::SetLevel2() | |||
| 1604 | AddLangString(s, langID); | 1610 | AddLangString(s, langID); |
| 1605 | } | 1611 | } |
| 1606 | } | 1612 | } |
| 1607 | const int index = (int)m_Level.AddString(s); | 1613 | m_Level.AddString_SetItemData(s, (LPARAM)i); |
| 1608 | m_Level.SetItemData(index, (LPARAM)i); | ||
| 1609 | } | 1614 | } |
| 1610 | } | 1615 | } |
| 1611 | SetNearestSelectComboBox(m_Level, level); | 1616 | SetNearestSelectComboBox(m_Level, level); |
| 1612 | } | 1617 | } |
| 1613 | 1618 | ||
| 1614 | 1619 | ||
| 1615 | static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s) | 1620 | static const char * const k_Auto_Prefix = "* "; |
| 1616 | { | ||
| 1617 | return cb.AddString((CSysString)s); | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | static const char *k_Auto_Prefix = "* "; | ||
| 1621 | 1621 | ||
| 1622 | static void Modify_Auto(AString &s) | 1622 | static void Modify_Auto(AString &s) |
| 1623 | { | 1623 | { |
| @@ -1690,8 +1690,8 @@ void CCompressDialog::SetMethod2(int keepMethodId) | |||
| 1690 | writtenMethodId = -1; | 1690 | writtenMethodId = -1; |
| 1691 | Modify_Auto(s); | 1691 | Modify_Auto(s); |
| 1692 | } | 1692 | } |
| 1693 | const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s); | 1693 | const int itemIndex = (int)ComboBox_AddStringAscii_SetItemData(m_Method, |
| 1694 | m_Method.SetItemData(itemIndex, writtenMethodId); | 1694 | s, writtenMethodId); |
| 1695 | if (keepMethodId == methodID) | 1695 | if (keepMethodId == methodID) |
| 1696 | { | 1696 | { |
| 1697 | m_Method.SetCurSel(itemIndex); | 1697 | m_Method.SetCurSel(itemIndex); |
| @@ -1731,7 +1731,7 @@ void CCompressDialog::SetEncryptionMethod() | |||
| 1731 | } | 1731 | } |
| 1732 | else if (ai.Is_Zip()) | 1732 | else if (ai.Is_Zip()) |
| 1733 | { | 1733 | { |
| 1734 | int index = FindRegistryFormat(ai.Name); | 1734 | const int index = FindRegistryFormat(ai.Name); |
| 1735 | UString encryptionMethod; | 1735 | UString encryptionMethod; |
| 1736 | if (index >= 0) | 1736 | if (index >= 0) |
| 1737 | { | 1737 | { |
| @@ -1836,9 +1836,7 @@ static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, si | |||
| 1836 | s.Add_Char('B'); | 1836 | s.Add_Char('B'); |
| 1837 | if (sizeReal == k_Auto_Dict) | 1837 | if (sizeReal == k_Auto_Dict) |
| 1838 | Modify_Auto(s); | 1838 | Modify_Auto(s); |
| 1839 | const int index = (int)ComboBox_AddStringAscii(cb, s); | 1839 | return (int)ComboBox_AddStringAscii_SetItemData(cb, s, (LPARAM)sizeReal); |
| 1840 | cb.SetItemData(index, (LPARAM)sizeReal); | ||
| 1841 | return index; | ||
| 1842 | } | 1840 | } |
| 1843 | 1841 | ||
| 1844 | int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) | 1842 | int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) |
| @@ -2201,9 +2199,7 @@ int CCompressDialog::AddOrder(UInt32 size) | |||
| 2201 | { | 2199 | { |
| 2202 | char s[32]; | 2200 | char s[32]; |
| 2203 | ConvertUInt32ToString(size, s); | 2201 | ConvertUInt32ToString(size, s); |
| 2204 | const int index = (int)ComboBox_AddStringAscii(m_Order, s); | 2202 | return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)size); |
| 2205 | m_Order.SetItemData(index, (LPARAM)size); | ||
| 2206 | return index; | ||
| 2207 | } | 2203 | } |
| 2208 | 2204 | ||
| 2209 | int CCompressDialog::AddOrder_Auto() | 2205 | int CCompressDialog::AddOrder_Auto() |
| @@ -2211,9 +2207,7 @@ int CCompressDialog::AddOrder_Auto() | |||
| 2211 | AString s; | 2207 | AString s; |
| 2212 | s.Add_UInt32(_auto_Order); | 2208 | s.Add_UInt32(_auto_Order); |
| 2213 | Modify_Auto(s); | 2209 | Modify_Auto(s); |
| 2214 | int index = (int)ComboBox_AddStringAscii(m_Order, s); | 2210 | return (int)ComboBox_AddStringAscii_SetItemData(m_Order, s, (LPARAM)(INT_PTR)(-1)); |
| 2215 | m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1)); | ||
| 2216 | return index; | ||
| 2217 | } | 2211 | } |
| 2218 | 2212 | ||
| 2219 | void CCompressDialog::SetOrder2() | 2213 | void CCompressDialog::SetOrder2() |
| @@ -2490,9 +2484,7 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2490 | AString s; | 2484 | AString s; |
| 2491 | Add_Size(s, _auto_Solid); | 2485 | Add_Size(s, _auto_Solid); |
| 2492 | Modify_Auto(s); | 2486 | Modify_Auto(s); |
| 2493 | const int index = (int)ComboBox_AddStringAscii(m_Solid, s); | 2487 | curSel = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)(Int32)-1); |
| 2494 | m_Solid.SetItemData(index, (LPARAM)(UInt32)(Int32)-1); | ||
| 2495 | curSel = index; | ||
| 2496 | } | 2488 | } |
| 2497 | 2489 | ||
| 2498 | if (is7z) | 2490 | if (is7z) |
| @@ -2501,8 +2493,7 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2501 | // kSolidLog_NoSolid = 0 for xz means default blockSize | 2493 | // kSolidLog_NoSolid = 0 for xz means default blockSize |
| 2502 | if (is7z) | 2494 | if (is7z) |
| 2503 | LangString(IDS_COMPRESS_NON_SOLID, s); | 2495 | LangString(IDS_COMPRESS_NON_SOLID, s); |
| 2504 | const int index = (int)m_Solid.AddString(s); | 2496 | const int index = (int)m_Solid.AddString_SetItemData(s, (LPARAM)(UInt32)kSolidLog_NoSolid); |
| 2505 | m_Solid.SetItemData(index, (LPARAM)(UInt32)kSolidLog_NoSolid); | ||
| 2506 | if (defaultBlockSize == kSolidLog_NoSolid) | 2497 | if (defaultBlockSize == kSolidLog_NoSolid) |
| 2507 | curSel = index; | 2498 | curSel = index; |
| 2508 | } | 2499 | } |
| @@ -2511,16 +2502,15 @@ void CCompressDialog::SetSolidBlockSize2() | |||
| 2511 | { | 2502 | { |
| 2512 | AString s; | 2503 | AString s; |
| 2513 | Add_Size(s, (UInt64)1 << i); | 2504 | Add_Size(s, (UInt64)1 << i); |
| 2514 | const int index = (int)ComboBox_AddStringAscii(m_Solid, s); | 2505 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_Solid, s, (LPARAM)(UInt32)i); |
| 2515 | m_Solid.SetItemData(index, (LPARAM)(UInt32)i); | ||
| 2516 | if (defaultBlockSize != (UInt32)(Int32)-1) | 2506 | if (defaultBlockSize != (UInt32)(Int32)-1) |
| 2517 | if (i <= defaultBlockSize || index <= 1) | 2507 | if (i <= defaultBlockSize || index <= 1) |
| 2518 | curSel = index; | 2508 | curSel = index; |
| 2519 | } | 2509 | } |
| 2520 | 2510 | ||
| 2521 | { | 2511 | { |
| 2522 | const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); | 2512 | const int index = (int)m_Solid.AddString_SetItemData( |
| 2523 | m_Solid.SetItemData(index, (LPARAM)kSolidLog_FullSolid); | 2513 | LangString(IDS_COMPRESS_SOLID), (LPARAM)kSolidLog_FullSolid); |
| 2524 | if (defaultBlockSize == kSolidLog_FullSolid) | 2514 | if (defaultBlockSize == kSolidLog_FullSolid) |
| 2525 | curSel = index; | 2515 | curSel = index; |
| 2526 | } | 2516 | } |
| @@ -2564,7 +2554,7 @@ static bool Is_Zstd_Mt_Supported() | |||
| 2564 | } | 2554 | } |
| 2565 | */ | 2555 | */ |
| 2566 | 2556 | ||
| 2567 | static const char *k_ST_Threads = " (ST)"; | 2557 | static const char * const k_ST_Threads = " (ST)"; |
| 2568 | 2558 | ||
| 2569 | void CCompressDialog::SetNumThreads2() | 2559 | void CCompressDialog::SetNumThreads2() |
| 2570 | { | 2560 | { |
| @@ -2575,15 +2565,31 @@ void CCompressDialog::SetNumThreads2() | |||
| 2575 | if (!fi.MultiThread_()) | 2565 | if (!fi.MultiThread_()) |
| 2576 | return; | 2566 | return; |
| 2577 | 2567 | ||
| 2578 | const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); | 2568 | UInt32 numCPUs = 1; // process threads |
| 2579 | // 64; // for debug: | 2569 | UInt32 numHardwareThreads = 1; // system threads |
| 2570 | NSystem::CProcessAffinity threadsInfo; | ||
| 2571 | threadsInfo.InitST(); | ||
| 2572 | #ifndef Z7_ST | ||
| 2573 | threadsInfo.Get_and_return_NumProcessThreads_and_SysThreads(numCPUs, numHardwareThreads); | ||
| 2574 | #endif | ||
| 2580 | 2575 | ||
| 2581 | UInt32 defaultValue = numHardwareThreads; | 2576 | AString s ("/ "); |
| 2577 | { | ||
| 2578 | s.Add_UInt32(numCPUs); | ||
| 2579 | if (numCPUs != numHardwareThreads) | ||
| 2580 | { | ||
| 2581 | s += " / "; | ||
| 2582 | s.Add_UInt32(numHardwareThreads); | ||
| 2583 | } | ||
| 2584 | SetItemTextA(IDT_COMPRESS_HARDWARE_THREADS, s.Ptr()); | ||
| 2585 | } | ||
| 2586 | |||
| 2587 | UInt32 defaultValue = numCPUs; | ||
| 2582 | bool useAutoThreads = true; | 2588 | bool useAutoThreads = true; |
| 2583 | 2589 | ||
| 2584 | { | 2590 | { |
| 2585 | const CArcInfoEx &ai = Get_ArcInfoEx(); | 2591 | const CArcInfoEx &ai = Get_ArcInfoEx(); |
| 2586 | int index = FindRegistryFormat(ai.Name); | 2592 | const int index = FindRegistryFormat(ai.Name); |
| 2587 | if (index >= 0) | 2593 | if (index >= 0) |
| 2588 | { | 2594 | { |
| 2589 | const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; | 2595 | const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; |
| @@ -2597,19 +2603,19 @@ void CCompressDialog::SetNumThreads2() | |||
| 2597 | 2603 | ||
| 2598 | // const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0; | 2604 | // const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0; |
| 2599 | 2605 | ||
| 2600 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; | ||
| 2601 | const int methodID = GetMethodID(); | 2606 | const int methodID = GetMethodID(); |
| 2602 | |||
| 2603 | const bool isZip = IsZipFormat(); | 2607 | const bool isZip = IsZipFormat(); |
| 2608 | |||
| 2609 | UInt32 numAlgoThreadsMax = numHardwareThreads * 2; // for unknow methods | ||
| 2604 | if (isZip) | 2610 | if (isZip) |
| 2605 | numAlgoThreadsMax = | 2611 | numAlgoThreadsMax = |
| 2606 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit | 2612 | 8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit |
| 2607 | else if (IsXzFormat()) | 2613 | else if (IsXzFormat()) |
| 2608 | numAlgoThreadsMax = 256 * 2; | 2614 | numAlgoThreadsMax = 256 * 2; // MTCODER_THREADS_MAX * 2 |
| 2609 | else switch (methodID) | 2615 | else switch (methodID) |
| 2610 | { | 2616 | { |
| 2611 | case kLZMA: numAlgoThreadsMax = 2; break; | 2617 | case kLZMA: numAlgoThreadsMax = 2; break; |
| 2612 | case kLZMA2: numAlgoThreadsMax = 256; break; | 2618 | case kLZMA2: numAlgoThreadsMax = 256 * 2; break; // MTCODER_THREADS_MAX * 2 |
| 2613 | case kBZip2: numAlgoThreadsMax = 64; break; | 2619 | case kBZip2: numAlgoThreadsMax = 64; break; |
| 2614 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; | 2620 | // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break; |
| 2615 | case kCopy: | 2621 | case kCopy: |
| @@ -2619,9 +2625,9 @@ void CCompressDialog::SetNumThreads2() | |||
| 2619 | case kPPMdZip: | 2625 | case kPPMdZip: |
| 2620 | numAlgoThreadsMax = 1; | 2626 | numAlgoThreadsMax = 1; |
| 2621 | } | 2627 | } |
| 2622 | UInt32 autoThreads = numHardwareThreads; | 2628 | UInt32 autoThreads = numCPUs; |
| 2623 | if (autoThreads > numAlgoThreadsMax) | 2629 | if (autoThreads > numAlgoThreadsMax) |
| 2624 | autoThreads = numAlgoThreadsMax; | 2630 | autoThreads = numAlgoThreadsMax; |
| 2625 | 2631 | ||
| 2626 | const UInt64 memUse_Limit = Get_MemUse_Bytes(); | 2632 | const UInt64 memUse_Limit = Get_MemUse_Bytes(); |
| 2627 | 2633 | ||
| @@ -2676,13 +2682,12 @@ void CCompressDialog::SetNumThreads2() | |||
| 2676 | 2682 | ||
| 2677 | int curSel = -1; | 2683 | int curSel = -1; |
| 2678 | { | 2684 | { |
| 2679 | AString s; | 2685 | s.Empty(); |
| 2680 | s.Add_UInt32(autoThreads); | 2686 | s.Add_UInt32(autoThreads); |
| 2681 | if (autoThreads == 0) s += k_ST_Threads; | 2687 | if (autoThreads == 0) s += k_ST_Threads; |
| 2682 | Modify_Auto(s); | 2688 | Modify_Auto(s); |
| 2683 | const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s); | 2689 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads, |
| 2684 | m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1)); | 2690 | s, (LPARAM)(INT_PTR)(-1)); |
| 2685 | // m_NumThreads.SetItemData(index, autoThreads); | ||
| 2686 | if (useAutoThreads) | 2691 | if (useAutoThreads) |
| 2687 | curSel = index; | 2692 | curSel = index; |
| 2688 | } | 2693 | } |
| @@ -2693,11 +2698,11 @@ void CCompressDialog::SetNumThreads2() | |||
| 2693 | 1; | 2698 | 1; |
| 2694 | i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) | 2699 | i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) |
| 2695 | { | 2700 | { |
| 2696 | AString s; | 2701 | s.Empty(); |
| 2697 | s.Add_UInt32(i); | 2702 | s.Add_UInt32(i); |
| 2698 | if (i == 0) s += k_ST_Threads; | 2703 | if (i == 0) s += k_ST_Threads; |
| 2699 | const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s); | 2704 | const int index = (int)ComboBox_AddStringAscii_SetItemData(m_NumThreads, |
| 2700 | m_NumThreads.SetItemData(index, (LPARAM)(UInt32)i); | 2705 | s, (LPARAM)(UInt32)i); |
| 2701 | if (!useAutoThreads && i == defaultValue) | 2706 | if (!useAutoThreads && i == defaultValue) |
| 2702 | curSel = index; | 2707 | curSel = index; |
| 2703 | } | 2708 | } |
| @@ -2754,9 +2759,7 @@ int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault) | |||
| 2754 | sRegistry.DeleteBack(); | 2759 | sRegistry.DeleteBack(); |
| 2755 | } | 2760 | } |
| 2756 | const unsigned dataIndex = _memUse_Strings.Add(sRegistry); | 2761 | const unsigned dataIndex = _memUse_Strings.Add(sRegistry); |
| 2757 | const int index = (int)m_MemUse.AddString(sUser); | 2762 | return (int)m_MemUse.AddString_SetItemData(sUser, (LPARAM)dataIndex); |
| 2758 | m_MemUse.SetItemData(index, (LPARAM)dataIndex); | ||
| 2759 | return index; | ||
| 2760 | } | 2763 | } |
| 2761 | 2764 | ||
| 2762 | 2765 | ||
| @@ -3439,11 +3442,7 @@ static const unsigned kTimePrec_1ns = 3; | |||
| 3439 | static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL) | 3442 | static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL) |
| 3440 | { | 3443 | { |
| 3441 | // s += " : "; | 3444 | // s += " : "; |
| 3442 | { | 3445 | s.Add_UInt32(val); |
| 3443 | AString s2; | ||
| 3444 | s2.Add_UInt32(val); | ||
| 3445 | s += s2; | ||
| 3446 | } | ||
| 3447 | s.Add_Space(); | 3446 | s.Add_Space(); |
| 3448 | s += unit; | 3447 | s += unit; |
| 3449 | if (sys) | 3448 | if (sys) |
| @@ -3476,9 +3475,7 @@ int COptionsDialog::AddPrec(unsigned prec, bool isDefault) | |||
| 3476 | } | 3475 | } |
| 3477 | else | 3476 | else |
| 3478 | s.Add_UInt32(prec); | 3477 | s.Add_UInt32(prec); |
| 3479 | const int index = (int)m_Prec.AddString(s); | 3478 | return (int)m_Prec.AddString_SetItemData(s, (LPARAM)writePrec); |
| 3480 | m_Prec.SetItemData(index, (LPARAM)writePrec); | ||
| 3481 | return index; | ||
| 3482 | } | 3479 | } |
| 3483 | 3480 | ||
| 3484 | 3481 | ||
diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index 9c3ed88..df1516c 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc | |||
| @@ -87,8 +87,8 @@ BEGIN | |||
| 87 | COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO | 87 | COMBOBOX IDC_COMPRESS_SOLID, g1x, 144, g1xs, 140, MY_COMBO |
| 88 | 88 | ||
| 89 | LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 | 89 | LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 |
| 90 | COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO | 90 | COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 40, 140, MY_COMBO |
| 91 | RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, MY_TEXT_NOPREFIX | 91 | RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 40, 167, 40, 16, SS_NOPREFIX |
| 92 | 92 | ||
| 93 | 93 | ||
| 94 | LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 | 94 | LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 |
diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index 4628482..467cf18 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp | |||
| @@ -102,8 +102,7 @@ void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned n | |||
| 102 | { | 102 | { |
| 103 | UString s = LangString(langIDs[i]); | 103 | UString s = LangString(langIDs[i]); |
| 104 | s.RemoveChar(L'&'); | 104 | s.RemoveChar(L'&'); |
| 105 | const int index = (int)combo.AddString(s); | 105 | combo.AddString_SetItemData(s, (LPARAM)i); |
| 106 | combo.SetItemData(index, (LPARAM)i); | ||
| 107 | if (values[i] == curVal) | 106 | if (values[i] == curVal) |
| 108 | curSel = i; | 107 | curSel = i; |
| 109 | } | 108 | } |
diff --git a/CPP/Common/Common0.h b/CPP/Common/Common0.h index 55606cd..5781a95 100644 --- a/CPP/Common/Common0.h +++ b/CPP/Common/Common0.h | |||
| @@ -126,8 +126,9 @@ if compiled with new GCC libstdc++, GCC libstdc++ can use: | |||
| 126 | #pragma GCC diagnostic ignored "-Wglobal-constructors" | 126 | #pragma GCC diagnostic ignored "-Wglobal-constructors" |
| 127 | #pragma GCC diagnostic ignored "-Wexit-time-destructors" | 127 | #pragma GCC diagnostic ignored "-Wexit-time-destructors" |
| 128 | 128 | ||
| 129 | #if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC | 129 | #if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 /* 18.1.0RC */ \ |
| 130 | #pragma GCC diagnostic ignored "-Wswitch-default" | 130 | || defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 16 // for APPLE=17 (LLVM=19) |
| 131 | #pragma GCC diagnostic ignored "-Wswitch-default" | ||
| 131 | #endif | 132 | #endif |
| 132 | // #pragma GCC diagnostic ignored "-Wunused-private-field" | 133 | // #pragma GCC diagnostic ignored "-Wunused-private-field" |
| 133 | // #pragma GCC diagnostic ignored "-Wnonportable-system-include-path" | 134 | // #pragma GCC diagnostic ignored "-Wnonportable-system-include-path" |
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h index 80f0205..08c10a3 100644 --- a/CPP/Common/MyBuffer.h +++ b/CPP/Common/MyBuffer.h | |||
| @@ -202,7 +202,53 @@ public: | |||
| 202 | } | 202 | } |
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | typedef CObjArray<Byte> CByteArr; | 205 | |
| 206 | /* CSmallObjArray can be used for Byte arrays | ||
| 207 | or for arrays whose total size in bytes does not exceed size_t ranges. | ||
| 208 | So there is no need to use Z7_ARRAY_NEW macro in CSmallObjArray code. */ | ||
| 209 | template <class T> class CSmallObjArray | ||
| 210 | { | ||
| 211 | protected: | ||
| 212 | T *_items; | ||
| 213 | private: | ||
| 214 | // we disable copy | ||
| 215 | CSmallObjArray(const CSmallObjArray &buffer); | ||
| 216 | void operator=(const CSmallObjArray &buffer); | ||
| 217 | public: | ||
| 218 | void Free() | ||
| 219 | { | ||
| 220 | delete []_items; | ||
| 221 | _items = NULL; | ||
| 222 | } | ||
| 223 | CSmallObjArray(size_t size): _items(NULL) | ||
| 224 | { | ||
| 225 | if (size != 0) | ||
| 226 | { | ||
| 227 | // Z7_ARRAY_NEW(_items, T, size) | ||
| 228 | _items = new T[size]; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | CSmallObjArray(): _items(NULL) {} | ||
| 232 | ~CSmallObjArray() { delete []_items; } | ||
| 233 | |||
| 234 | operator T *() { return _items; } | ||
| 235 | operator const T *() const { return _items; } | ||
| 236 | const T* ConstData() const { return _items; } | ||
| 237 | T* NonConstData() const { return _items; } | ||
| 238 | T* NonConstData() { return _items; } | ||
| 239 | // const T* Data() const { return _items; } | ||
| 240 | // T* Data() { return _items; } | ||
| 241 | |||
| 242 | void Alloc(size_t newSize) | ||
| 243 | { | ||
| 244 | delete []_items; | ||
| 245 | _items = NULL; | ||
| 246 | // Z7_ARRAY_NEW(_items, T, newSize) | ||
| 247 | _items = new T[newSize]; | ||
| 248 | } | ||
| 249 | }; | ||
| 250 | |||
| 251 | typedef CSmallObjArray<Byte> CByteArr; | ||
| 206 | typedef CObjArray<bool> CBoolArr; | 252 | typedef CObjArray<bool> CBoolArr; |
| 207 | typedef CObjArray<int> CIntArr; | 253 | typedef CObjArray<int> CIntArr; |
| 208 | typedef CObjArray<unsigned> CUIntArr; | 254 | typedef CObjArray<unsigned> CUIntArr; |
diff --git a/CPP/Windows/Control/ComboBox.cpp b/CPP/Windows/Control/ComboBox.cpp index 8da487d..2e9c8cb 100644 --- a/CPP/Windows/Control/ComboBox.cpp +++ b/CPP/Windows/Control/ComboBox.cpp | |||
| @@ -63,4 +63,13 @@ LRESULT CComboBox::GetLBText(int index, UString &s) | |||
| 63 | } | 63 | } |
| 64 | #endif | 64 | #endif |
| 65 | 65 | ||
| 66 | LRESULT CComboBox::AddString_SetItemData(LPCWSTR s, LPARAM lParam) | ||
| 67 | { | ||
| 68 | const LRESULT index = AddString(s); | ||
| 69 | // NOTE: SetItemData((int)-1, lParam) works as unexpected. | ||
| 70 | if (index >= 0) // optional check, because (index < 0) is not expected for normal inputs | ||
| 71 | SetItemData((int)index, lParam); | ||
| 72 | return index; | ||
| 73 | } | ||
| 74 | |||
| 66 | }} | 75 | }} |
diff --git a/CPP/Windows/Control/ComboBox.h b/CPP/Windows/Control/ComboBox.h index 2a60b8a..224efca 100644 --- a/CPP/Windows/Control/ComboBox.h +++ b/CPP/Windows/Control/ComboBox.h | |||
| @@ -21,6 +21,8 @@ public: | |||
| 21 | LRESULT AddString(LPCWSTR s); | 21 | LRESULT AddString(LPCWSTR s); |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
| 24 | LRESULT AddString_SetItemData(LPCWSTR s, LPARAM lParam); | ||
| 25 | |||
| 24 | /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ | 26 | /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/ |
| 25 | LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); } | 27 | LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); } |
| 26 | LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); } | 28 | LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); } |
diff --git a/CPP/Windows/FileFind.cpp b/CPP/Windows/FileFind.cpp index 64075ab..669541e 100644 --- a/CPP/Windows/FileFind.cpp +++ b/CPP/Windows/FileFind.cpp | |||
| @@ -1162,6 +1162,15 @@ void CFileInfoBase::SetFrom_stat(const struct stat &st) | |||
| 1162 | MTime = st.st_mtimespec; | 1162 | MTime = st.st_mtimespec; |
| 1163 | ATime = st.st_atimespec; | 1163 | ATime = st.st_atimespec; |
| 1164 | 1164 | ||
| 1165 | #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__) | ||
| 1166 | |||
| 1167 | // CTime = ST_CTIME(st); | ||
| 1168 | // MTime = ST_MTIME(st); | ||
| 1169 | // ATime = ST_ATIME(st); | ||
| 1170 | CTime.tv_sec = st.st_ctime; CTime.tv_nsec = 0; | ||
| 1171 | MTime.tv_sec = st.st_mtime; MTime.tv_nsec = 0; | ||
| 1172 | ATime.tv_sec = st.st_atime; ATime.tv_nsec = 0; | ||
| 1173 | |||
| 1165 | #else | 1174 | #else |
| 1166 | // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); | 1175 | // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100); |
| 1167 | // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); | 1176 | // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100); |
| @@ -1312,7 +1321,7 @@ bool CDirEntry::IsDots() const throw() | |||
| 1312 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) | 1321 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) |
| 1313 | we can call fstatat() for that case, but we use only (Name) check here */ | 1322 | we can call fstatat() for that case, but we use only (Name) check here */ |
| 1314 | 1323 | ||
| 1315 | #if !defined(_AIX) && !defined(__sun) | 1324 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 1316 | if (Type != DT_DIR && Type != DT_UNKNOWN) | 1325 | if (Type != DT_DIR && Type != DT_UNKNOWN) |
| 1317 | return false; | 1326 | return false; |
| 1318 | #endif | 1327 | #endif |
| @@ -1352,7 +1361,7 @@ bool CEnumerator::NextAny(CDirEntry &fi, bool &found) | |||
| 1352 | 1361 | ||
| 1353 | fi.iNode = de->d_ino; | 1362 | fi.iNode = de->d_ino; |
| 1354 | 1363 | ||
| 1355 | #if !defined(_AIX) && !defined(__sun) | 1364 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 1356 | fi.Type = de->d_type; | 1365 | fi.Type = de->d_type; |
| 1357 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) | 1366 | /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN) |
| 1358 | we can set (Type) from fstatat() in that case. | 1367 | we can set (Type) from fstatat() in that case. |
diff --git a/CPP/Windows/FileFind.h b/CPP/Windows/FileFind.h index f68673a..944bca2 100644 --- a/CPP/Windows/FileFind.h +++ b/CPP/Windows/FileFind.h | |||
| @@ -277,13 +277,13 @@ typedef CFileInfo CDirEntry; | |||
| 277 | struct CDirEntry | 277 | struct CDirEntry |
| 278 | { | 278 | { |
| 279 | ino_t iNode; | 279 | ino_t iNode; |
| 280 | #if !defined(_AIX) && !defined(__sun) | 280 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 281 | Byte Type; | 281 | Byte Type; |
| 282 | #endif | 282 | #endif |
| 283 | FString Name; | 283 | FString Name; |
| 284 | 284 | ||
| 285 | /* | 285 | /* |
| 286 | #if !defined(_AIX) && !defined(__sun) | 286 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 287 | bool IsDir() const | 287 | bool IsDir() const |
| 288 | { | 288 | { |
| 289 | // (Type == DT_UNKNOWN) on some systems | 289 | // (Type == DT_UNKNOWN) on some systems |
| @@ -310,7 +310,7 @@ public: | |||
| 310 | bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; | 310 | bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const; |
| 311 | bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const | 311 | bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const |
| 312 | { | 312 | { |
| 313 | #if !defined(_AIX) && !defined(__sun) | 313 | #if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__) |
| 314 | if (de.Type == DT_DIR) | 314 | if (de.Type == DT_DIR) |
| 315 | return true; | 315 | return true; |
| 316 | if (de.Type != DT_UNKNOWN) | 316 | if (de.Type != DT_UNKNOWN) |
diff --git a/CPP/Windows/SecurityUtils.h b/CPP/Windows/SecurityUtils.h index 7219f06..022a8f3 100644 --- a/CPP/Windows/SecurityUtils.h +++ b/CPP/Windows/SecurityUtils.h | |||
| @@ -3,7 +3,11 @@ | |||
| 3 | #ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H | 3 | #ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H |
| 4 | #define ZIP7_INC_WINDOWS_SECURITY_UTILS_H | 4 | #define ZIP7_INC_WINDOWS_SECURITY_UTILS_H |
| 5 | 5 | ||
| 6 | #if defined(__MINGW32__) || defined(__MINGW64__) | ||
| 7 | #include <ntsecapi.h> | ||
| 8 | #else | ||
| 6 | #include <NTSecAPI.h> | 9 | #include <NTSecAPI.h> |
| 10 | #endif | ||
| 7 | 11 | ||
| 8 | #include "Defs.h" | 12 | #include "Defs.h" |
| 9 | 13 | ||
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 4745785..6999ef9 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp | |||
| @@ -5,8 +5,9 @@ | |||
| 5 | #ifndef _WIN32 | 5 | #ifndef _WIN32 |
| 6 | #include <unistd.h> | 6 | #include <unistd.h> |
| 7 | #include <limits.h> | 7 | #include <limits.h> |
| 8 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 8 | #if defined(__APPLE__) || defined(__DragonFly__) \ |
| 9 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 9 | || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ |
| 10 | || defined(__QNXNTO__) | ||
| 10 | #include <sys/sysctl.h> | 11 | #include <sys/sysctl.h> |
| 11 | #else | 12 | #else |
| 12 | #include <sys/sysinfo.h> | 13 | #include <sys/sysinfo.h> |
| @@ -299,8 +300,9 @@ bool GetRamSize(size_t &size) | |||
| 299 | size = (size_t)sizeof(size_t) << 29; | 300 | size = (size_t)sizeof(size_t) << 29; |
| 300 | size64 = size; | 301 | size64 = size; |
| 301 | 302 | ||
| 302 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 303 | #if defined(__APPLE__) || defined(__DragonFly__) \ |
| 303 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 304 | || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ |
| 305 | || defined(__QNXNTO__) | ||
| 304 | 306 | ||
| 305 | uint64_t val = 0; | 307 | uint64_t val = 0; |
| 306 | int mib[2]; | 308 | int mib[2]; |
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index 0c80373..041a44d 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | namespace NWindows { | 15 | namespace NWindows { |
| 16 | namespace NSystem { | 16 | namespace NSystem { |
| 17 | 17 | ||
| 18 | UInt32 GetNumberOfProcessors(); | ||
| 19 | |||
| 18 | #ifdef _WIN32 | 20 | #ifdef _WIN32 |
| 19 | 21 | ||
| 20 | struct CCpuGroups | 22 | struct CCpuGroups |
| @@ -103,6 +105,25 @@ struct CProcessAffinity | |||
| 103 | return CountAffinity(systemAffinityMask); | 105 | return CountAffinity(systemAffinityMask); |
| 104 | } | 106 | } |
| 105 | 107 | ||
| 108 | // it returns normilized number of threads | ||
| 109 | void Get_and_return_NumProcessThreads_and_SysThreads(UInt32 &numProcessThreads, UInt32 &numSysThreads) | ||
| 110 | { | ||
| 111 | UInt32 num1 = 0, num2 = 0; | ||
| 112 | if (Get()) | ||
| 113 | { | ||
| 114 | num1 = GetNumProcessThreads(); | ||
| 115 | num2 = GetNumSystemThreads(); | ||
| 116 | } | ||
| 117 | if (num1 == 0) | ||
| 118 | num1 = NSystem::GetNumberOfProcessors(); | ||
| 119 | if (num1 == 0) | ||
| 120 | num1 = 1; | ||
| 121 | if (num2 < num1) | ||
| 122 | num2 = num1; | ||
| 123 | numProcessThreads = num1; | ||
| 124 | numSysThreads = num2; | ||
| 125 | } | ||
| 126 | |||
| 106 | BOOL Get(); | 127 | BOOL Get(); |
| 107 | 128 | ||
| 108 | BOOL SetProcAffinity() const | 129 | BOOL SetProcAffinity() const |
| @@ -177,8 +198,6 @@ struct CProcessAffinity | |||
| 177 | #endif // _WIN32 | 198 | #endif // _WIN32 |
| 178 | 199 | ||
| 179 | 200 | ||
| 180 | UInt32 GetNumberOfProcessors(); | ||
| 181 | |||
| 182 | bool GetRamSize(size_t &size); // returns false, if unknown ram size | 201 | bool GetRamSize(size_t &size); // returns false, if unknown ram size |
| 183 | 202 | ||
| 184 | unsigned long Get_File_OPEN_MAX(); | 203 | unsigned long Get_File_OPEN_MAX(); |
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp index 35846e0..2eced2a 100644 --- a/CPP/Windows/SystemInfo.cpp +++ b/CPP/Windows/SystemInfo.cpp | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) | 23 | #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) |
| 24 | #define Z7_GETAUXV_AVAILABLE | 24 | #define Z7_GETAUXV_AVAILABLE |
| 25 | #else | 25 | #elif !defined(__QNXNTO__) |
| 26 | // #pragma message("=== is not NEW GLIBC === ") | 26 | // #pragma message("=== is not NEW GLIBC === ") |
| 27 | #if defined __has_include | 27 | #if defined __has_include |
| 28 | #if __has_include (<sys/auxv.h>) | 28 | #if __has_include (<sys/auxv.h>) |
| @@ -58,7 +58,7 @@ | |||
| 58 | 58 | ||
| 59 | #ifdef USE_HWCAP | 59 | #ifdef USE_HWCAP |
| 60 | 60 | ||
| 61 | #if defined(__FreeBSD__) | 61 | #if defined(__FreeBSD__) || defined(__OpenBSD__) |
| 62 | 62 | ||
| 63 | // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???) | 63 | // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???) |
| 64 | static unsigned long MY_getauxval(int aux) | 64 | static unsigned long MY_getauxval(int aux) |
diff --git a/CPP/Windows/TimeUtils.h b/CPP/Windows/TimeUtils.h index 4a9d0f2..8e1e478 100644 --- a/CPP/Windows/TimeUtils.h +++ b/CPP/Windows/TimeUtils.h | |||
| @@ -65,6 +65,14 @@ inline bool FILETIME_IsZero(const FILETIME &ft) | |||
| 65 | #define ST_MTIME(st) st.st_mtimespec | 65 | #define ST_MTIME(st) st.st_mtimespec |
| 66 | #define ST_ATIME(st) st.st_atimespec | 66 | #define ST_ATIME(st) st.st_atimespec |
| 67 | #define ST_CTIME(st) st.st_ctimespec | 67 | #define ST_CTIME(st) st.st_ctimespec |
| 68 | #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__) | ||
| 69 | // QNX armv7le (32-bit) for "struct stat" timestamps uses time_t instead of timespec | ||
| 70 | inline CFiTime ST_MTIME(const struct stat &st) | ||
| 71 | { timespec ts; ts.tv_sec = st.st_mtime; ts.tv_nsec = 0; return ts; } | ||
| 72 | inline CFiTime ST_ATIME(const struct stat &st) | ||
| 73 | { timespec ts; ts.tv_sec = st.st_atime; ts.tv_nsec = 0; return ts; } | ||
| 74 | inline CFiTime ST_CTIME(const struct stat &st) | ||
| 75 | { timespec ts; ts.tv_sec = st.st_ctime; ts.tv_nsec = 0; return ts; } | ||
| 68 | #else | 76 | #else |
| 69 | #define ST_MTIME(st) st.st_mtim | 77 | #define ST_MTIME(st) st.st_mtim |
| 70 | #define ST_ATIME(st) st.st_atim | 78 | #define ST_ATIME(st) st.st_atim |
