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