1 // OpenArchive.h 2 3 #ifndef __OPEN_ARCHIVE_H 4 #define __OPEN_ARCHIVE_H 5 6 #include "../../../Windows/PropVariant.h" 7 8 #include "ArchiveOpenCallback.h" 9 #include "LoadCodecs.h" 10 #include "Property.h" 11 12 #ifndef _SFX 13 14 #define SUPPORT_ALT_STREAMS 15 16 #endif 17 18 HRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw(); 19 HRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw(); 20 HRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw(); 21 HRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw(); 22 HRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw(); 23 24 #ifdef SUPPORT_ALT_STREAMS 25 int FindAltStreamColon_in_Path(const wchar_t *path); 26 #endif 27 28 /* 29 struct COptionalOpenProperties 30 { 31 UString FormatName; 32 CObjectVector<CProperty> Props; 33 }; 34 */ 35 36 #ifdef _SFX 37 #define OPEN_PROPS_DECL 38 #else 39 #define OPEN_PROPS_DECL const CObjectVector<CProperty> *props; 40 // #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props 41 #endif 42 43 struct COpenSpecFlags 44 { 45 // bool CanReturnFull; 46 bool CanReturnFrontal; 47 bool CanReturnTail; 48 bool CanReturnMid; 49 CanReturn_NonStartCOpenSpecFlags50 bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; } 51 COpenSpecFlagsCOpenSpecFlags52 COpenSpecFlags(): 53 // CanReturnFull(true), 54 CanReturnFrontal(false), 55 CanReturnTail(false), 56 CanReturnMid(false) 57 {} 58 }; 59 60 struct COpenType 61 { 62 int FormatIndex; 63 64 COpenSpecFlags SpecForcedType; 65 COpenSpecFlags SpecMainType; 66 COpenSpecFlags SpecWrongExt; 67 COpenSpecFlags SpecUnknownExt; 68 69 bool Recursive; 70 71 bool CanReturnArc; 72 bool CanReturnParser; 73 bool IsHashType; 74 bool EachPos; 75 76 // bool SkipSfxStub; 77 // bool ExeAsUnknown; 78 79 bool ZerosTailIsAllowed; 80 81 bool MaxStartOffset_Defined; 82 UInt64 MaxStartOffset; 83 GetSpecCOpenType84 const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const 85 { 86 return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); 87 } 88 COpenTypeCOpenType89 COpenType(): 90 FormatIndex(-1), 91 Recursive(true), 92 CanReturnArc(true), 93 CanReturnParser(false), 94 IsHashType(false), 95 EachPos(false), 96 // SkipSfxStub(true), 97 // ExeAsUnknown(true), 98 ZerosTailIsAllowed(false), 99 MaxStartOffset_Defined(false), 100 MaxStartOffset(0) 101 { 102 SpecForcedType.CanReturnFrontal = true; 103 SpecForcedType.CanReturnTail = true; 104 SpecForcedType.CanReturnMid = true; 105 106 SpecMainType.CanReturnFrontal = true; 107 108 SpecUnknownExt.CanReturnTail = true; // for sfx 109 SpecUnknownExt.CanReturnMid = true; 110 SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad 111 112 // ZerosTailIsAllowed = true; 113 } 114 }; 115 116 struct COpenOptions 117 { 118 CCodecs *codecs; 119 COpenType openType; 120 const CObjectVector<COpenType> *types; 121 const CIntVector *excludedFormats; 122 123 IInStream *stream; 124 ISequentialInStream *seqStream; 125 IArchiveOpenCallback *callback; 126 COpenCallbackImp *callbackSpec; // it's used for SFX only 127 OPEN_PROPS_DECL 128 // bool openOnlySpecifiedByExtension, 129 130 bool stdInMode; 131 UString filePath; 132 COpenOptionsCOpenOptions133 COpenOptions(): 134 codecs(NULL), 135 types(NULL), 136 excludedFormats(NULL), 137 stream(NULL), 138 seqStream(NULL), 139 callback(NULL), 140 callbackSpec(NULL), 141 stdInMode(false) 142 {} 143 144 }; 145 146 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); 147 148 struct CArcErrorInfo 149 { 150 bool ThereIsTail; 151 bool UnexpecedEnd; 152 bool IgnoreTail; // all are zeros 153 // bool NonZerosTail; 154 bool ErrorFlags_Defined; 155 UInt32 ErrorFlags; 156 UInt32 WarningFlags; 157 int ErrorFormatIndex; // - 1 means no Error. 158 // if FormatIndex == ErrorFormatIndex, the archive is open with offset 159 UInt64 TailSize; 160 161 /* if CArc is Open OK with some format: 162 - ErrorFormatIndex shows error format index, if extension is incorrect 163 - other variables show message and warnings of archive that is open */ 164 165 UString ErrorMessage; 166 UString WarningMessage; 167 168 // call IsArc_After_NonOpen only if Open returns S_FALSE IsArc_After_NonOpenCArcErrorInfo169 bool IsArc_After_NonOpen() const 170 { 171 return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); 172 } 173 174 CArcErrorInfoCArcErrorInfo175 CArcErrorInfo(): 176 ThereIsTail(false), 177 UnexpecedEnd(false), 178 IgnoreTail(false), 179 // NonZerosTail(false), 180 ErrorFlags_Defined(false), 181 ErrorFlags(0), 182 WarningFlags(0), 183 ErrorFormatIndex(-1), 184 TailSize(0) 185 {} 186 187 void ClearErrors(); 188 ClearErrors_FullCArcErrorInfo189 void ClearErrors_Full() 190 { 191 ErrorFormatIndex = -1; 192 ClearErrors(); 193 } 194 IsThereErrorOrWarningCArcErrorInfo195 bool IsThereErrorOrWarning() const 196 { 197 return ErrorFlags != 0 198 || WarningFlags != 0 199 || NeedTailWarning() 200 || UnexpecedEnd 201 || !ErrorMessage.IsEmpty() 202 || !WarningMessage.IsEmpty(); 203 } 204 AreThereErrorsCArcErrorInfo205 bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } AreThereWarningsCArcErrorInfo206 bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } 207 NeedTailWarningCArcErrorInfo208 bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } 209 GetWarningFlagsCArcErrorInfo210 UInt32 GetWarningFlags() const 211 { 212 UInt32 a = WarningFlags; 213 if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) 214 a |= kpv_ErrorFlags_DataAfterEnd; 215 return a; 216 } 217 GetErrorFlagsCArcErrorInfo218 UInt32 GetErrorFlags() const 219 { 220 UInt32 a = ErrorFlags; 221 if (UnexpecedEnd) 222 a |= kpv_ErrorFlags_UnexpectedEnd; 223 return a; 224 } 225 }; 226 227 struct CReadArcItem 228 { 229 UString Path; // Path from root (including alt stream name, if alt stream) 230 UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode 231 232 #ifdef SUPPORT_ALT_STREAMS 233 UString MainPath; 234 /* MainPath = Path for non-AltStream, 235 MainPath = Path of parent, if there is parent for AltStream. */ 236 UString AltStreamName; 237 bool IsAltStream; 238 bool WriteToAltStreamIfColon; 239 #endif 240 241 bool IsDir; 242 bool MainIsDir; 243 UInt32 ParentIndex; // use it, if IsAltStream 244 245 #ifndef _SFX 246 bool _use_baseParentFolder_mode; 247 int _baseParentFolder; 248 #endif 249 CReadArcItemCReadArcItem250 CReadArcItem() 251 { 252 #ifdef SUPPORT_ALT_STREAMS 253 WriteToAltStreamIfColon = false; 254 #endif 255 256 #ifndef _SFX 257 _use_baseParentFolder_mode = false; 258 _baseParentFolder = -1; 259 #endif 260 } 261 }; 262 263 class CArc 264 { 265 HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive); 266 HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); 267 HRESULT OpenStream2(const COpenOptions &options); 268 269 #ifndef _SFX 270 // parts.Back() can contain alt stream name "nams:AltName" 271 HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; 272 #endif 273 274 public: 275 CMyComPtr<IInArchive> Archive; 276 CMyComPtr<IInStream> InStream; 277 // we use InStream in 2 cases (ArcStreamOffset != 0): 278 // 1) if we use additional cache stream 279 // 2) we reopen sfx archive with CTailInStream 280 281 CMyComPtr<IArchiveGetRawProps> GetRawProps; 282 CMyComPtr<IArchiveGetRootProps> GetRootProps; 283 284 CArcErrorInfo ErrorInfo; // for OK archives 285 CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) 286 287 UString Path; 288 UString filePath; 289 UString DefaultName; 290 int FormatIndex; // -1 means Parser 291 UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile 292 FILETIME MTime; 293 bool MTimeDefined; 294 295 Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler 296 UInt64 PhySize; 297 // UInt64 OkPhySize; 298 bool PhySizeDefined; 299 // bool OkPhySize_Defined; 300 UInt64 FileSize; 301 UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file 302 // bool offsetDefined; 303 GetEstmatedPhySize()304 UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; } 305 306 UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler GetGlobalOffset()307 Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive 308 309 // AString ErrorFlagsText; 310 311 bool IsParseArc; 312 313 bool IsTree; 314 bool IsReadOnly; 315 316 bool Ask_Deleted; 317 bool Ask_AltStream; 318 bool Ask_Aux; 319 bool Ask_INode; 320 321 bool IgnoreSplit; // don't try split handler 322 323 // void Set_ErrorFlagsText(); 324 CArc()325 CArc(): 326 MTimeDefined(false), 327 IsTree(false), 328 IsReadOnly(false), 329 Ask_Deleted(false), 330 Ask_AltStream(false), 331 Ask_Aux(false), 332 Ask_INode(false), 333 IgnoreSplit(false) 334 {} 335 336 HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); 337 338 // ~CArc(); 339 Close()340 HRESULT Close() 341 { 342 InStream.Release(); 343 return Archive->Close(); 344 } 345 346 HRESULT GetItemPath(UInt32 index, UString &result) const; 347 HRESULT GetDefaultItemPath(UInt32 index, UString &result) const; 348 349 // GetItemPath2 adds [DELETED] dir prefix for deleted items. 350 HRESULT GetItemPath2(UInt32 index, UString &result) const; 351 352 HRESULT GetItem(UInt32 index, CReadArcItem &item) const; 353 354 HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; 355 HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; IsItemAnti(UInt32 index,bool & result)356 HRESULT IsItemAnti(UInt32 index, bool &result) const 357 { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } 358 359 360 HRESULT OpenStream(const COpenOptions &options); 361 HRESULT OpenStreamOrFile(COpenOptions &options); 362 363 HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional); 364 365 HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream); 366 IsHashHandler(const COpenOptions & options)367 bool IsHashHandler(const COpenOptions &options) const 368 { 369 if (FormatIndex < 0) 370 return false; 371 return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler(); 372 } 373 }; 374 375 struct CArchiveLink 376 { 377 CObjectVector<CArc> Arcs; 378 UStringVector VolumePaths; 379 UInt64 VolumesSize; 380 bool IsOpen; 381 382 bool PasswordWasAsked; 383 // UString Password; 384 385 // int NonOpenErrorFormatIndex; // - 1 means no Error. 386 UString NonOpen_ArcPath; 387 388 CArcErrorInfo NonOpen_ErrorInfo; 389 390 // UString ErrorsText; 391 // void Set_ErrorsText(); 392 CArchiveLinkCArchiveLink393 CArchiveLink(): 394 VolumesSize(0), 395 IsOpen(false), 396 PasswordWasAsked(false) 397 {} 398 399 void KeepModeForNextOpen(); 400 HRESULT Close(); 401 void Release(); ~CArchiveLinkCArchiveLink402 ~CArchiveLink() { Release(); } 403 GetArcCArchiveLink404 const CArc *GetArc() const { return &Arcs.Back(); } GetArchiveCArchiveLink405 IInArchive *GetArchive() const { return Arcs.Back().Archive; } GetArchiveGetRawPropsCArchiveLink406 IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } GetArchiveGetRootPropsCArchiveLink407 IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } 408 409 /* 410 Open() opens archive and COpenOptions::callback 411 Open2() uses COpenCallbackImp that implements Volumes and password callback 412 Open3() calls Open2() and callbackUI->Open_Finished(); 413 Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive. 414 */ 415 416 HRESULT Open(COpenOptions &options); 417 HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); 418 HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); 419 Open_StrictCArchiveLink420 HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI) 421 { 422 HRESULT result = Open3(options, callbackUI); 423 if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0) 424 result = S_FALSE; 425 return result; 426 } 427 428 HRESULT ReOpen(COpenOptions &options); 429 }; 430 431 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types); 432 433 // bool IsHashType(const CObjectVector<COpenType> &types); 434 435 436 struct CDirPathSortPair 437 { 438 unsigned Len; 439 unsigned Index; 440 441 void SetNumSlashes(const FChar *s); 442 CompareCDirPathSortPair443 int Compare(const CDirPathSortPair &a) const 444 { 445 // We need sorting order where parent items will be after child items 446 if (Len < a.Len) return 1; 447 if (Len > a.Len) return -1; 448 if (Index < a.Index) return -1; 449 if (Index > a.Index) return 1; 450 return 0; 451 } 452 }; 453 454 #endif 455