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 EachPos; 74 75 // bool SkipSfxStub; 76 // bool ExeAsUnknown; 77 78 bool ZerosTailIsAllowed; 79 80 bool MaxStartOffset_Defined; 81 UInt64 MaxStartOffset; 82 GetSpecCOpenType83 const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const 84 { 85 return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt)); 86 } 87 COpenTypeCOpenType88 COpenType(): 89 FormatIndex(-1), 90 Recursive(true), 91 EachPos(false), 92 CanReturnArc(true), 93 CanReturnParser(false), 94 // SkipSfxStub(true), 95 // ExeAsUnknown(true), 96 ZerosTailIsAllowed(false), 97 MaxStartOffset_Defined(false), 98 MaxStartOffset(0) 99 { 100 SpecForcedType.CanReturnFrontal = true; 101 SpecForcedType.CanReturnTail = true; 102 SpecForcedType.CanReturnMid = true; 103 104 SpecMainType.CanReturnFrontal = true; 105 106 SpecUnknownExt.CanReturnTail = true; // for sfx 107 SpecUnknownExt.CanReturnMid = true; 108 SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad 109 110 // ZerosTailIsAllowed = true; 111 } 112 }; 113 114 struct COpenOptions 115 { 116 CCodecs *codecs; 117 COpenType openType; 118 const CObjectVector<COpenType> *types; 119 const CIntVector *excludedFormats; 120 121 IInStream *stream; 122 ISequentialInStream *seqStream; 123 IArchiveOpenCallback *callback; 124 COpenCallbackImp *callbackSpec; 125 OPEN_PROPS_DECL 126 // bool openOnlySpecifiedByExtension, 127 128 bool stdInMode; 129 UString filePath; 130 COpenOptionsCOpenOptions131 COpenOptions(): 132 codecs(NULL), 133 types(NULL), 134 excludedFormats(NULL), 135 stream(NULL), 136 seqStream(NULL), 137 callback(NULL), 138 callbackSpec(NULL), 139 stdInMode(false) 140 {} 141 142 }; 143 144 UInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL); 145 146 struct CArcErrorInfo 147 { 148 bool ThereIsTail; 149 bool UnexpecedEnd; 150 bool IgnoreTail; // all are zeros 151 // bool NonZerosTail; 152 bool ErrorFlags_Defined; 153 UInt32 ErrorFlags; 154 UInt32 WarningFlags; 155 int ErrorFormatIndex; // - 1 means no Error. 156 // if FormatIndex == ErrorFormatIndex, the archive is open with offset 157 UInt64 TailSize; 158 159 /* if CArc is Open OK with some format: 160 - ErrorFormatIndex shows error format index, if extension is incorrect 161 - other variables show message and warnings of archive that is open */ 162 163 UString ErrorMessage; 164 UString WarningMessage; 165 166 // call IsArc_After_NonOpen only if Open returns S_FALSE IsArc_After_NonOpenCArcErrorInfo167 bool IsArc_After_NonOpen() const 168 { 169 return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0); 170 } 171 172 CArcErrorInfoCArcErrorInfo173 CArcErrorInfo(): 174 ThereIsTail(false), 175 UnexpecedEnd(false), 176 IgnoreTail(false), 177 // NonZerosTail(false), 178 ErrorFlags_Defined(false), 179 ErrorFlags(0), 180 WarningFlags(0), 181 ErrorFormatIndex(-1), 182 TailSize(0) 183 {} 184 185 void ClearErrors(); 186 ClearErrors_FullCArcErrorInfo187 void ClearErrors_Full() 188 { 189 ErrorFormatIndex = -1; 190 ClearErrors(); 191 } 192 IsThereErrorOrWarningCArcErrorInfo193 bool IsThereErrorOrWarning() const 194 { 195 return ErrorFlags != 0 196 || WarningFlags != 0 197 || NeedTailWarning() 198 || UnexpecedEnd 199 || !ErrorMessage.IsEmpty() 200 || !WarningMessage.IsEmpty(); 201 } 202 AreThereErrorsCArcErrorInfo203 bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; } AreThereWarningsCArcErrorInfo204 bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); } 205 NeedTailWarningCArcErrorInfo206 bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; } 207 GetWarningFlagsCArcErrorInfo208 UInt32 GetWarningFlags() const 209 { 210 UInt32 a = WarningFlags; 211 if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0) 212 a |= kpv_ErrorFlags_DataAfterEnd; 213 return a; 214 } 215 GetErrorFlagsCArcErrorInfo216 UInt32 GetErrorFlags() const 217 { 218 UInt32 a = ErrorFlags; 219 if (UnexpecedEnd) 220 a |= kpv_ErrorFlags_UnexpectedEnd; 221 return a; 222 } 223 }; 224 225 struct CReadArcItem 226 { 227 UString Path; // Path from root (including alt stream name, if alt stream) 228 UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode 229 230 #ifdef SUPPORT_ALT_STREAMS 231 UString MainPath; 232 /* MainPath = Path for non-AltStream, 233 MainPath = Path of parent, if there is parent for AltStream. */ 234 UString AltStreamName; 235 bool IsAltStream; 236 bool WriteToAltStreamIfColon; 237 #endif 238 239 bool IsDir; 240 bool MainIsDir; 241 UInt32 ParentIndex; // use it, if IsAltStream 242 243 #ifndef _SFX 244 bool _use_baseParentFolder_mode; 245 int _baseParentFolder; 246 #endif 247 CReadArcItemCReadArcItem248 CReadArcItem() 249 { 250 #ifdef SUPPORT_ALT_STREAMS 251 WriteToAltStreamIfColon = false; 252 #endif 253 254 #ifndef _SFX 255 _use_baseParentFolder_mode = false; 256 _baseParentFolder = -1; 257 #endif 258 } 259 }; 260 261 class CArc 262 { 263 HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive); 264 HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset); 265 HRESULT OpenStream2(const COpenOptions &options); 266 267 #ifndef _SFX 268 // parts.Back() can contain alt stream name "nams:AltName" 269 HRESULT GetItemPathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const; 270 #endif 271 272 public: 273 CMyComPtr<IInArchive> Archive; 274 CMyComPtr<IInStream> InStream; 275 // we use InStream in 2 cases (ArcStreamOffset != 0): 276 // 1) if we use additional cache stream 277 // 2) we reopen sfx archive with CTailInStream 278 279 CMyComPtr<IArchiveGetRawProps> GetRawProps; 280 CMyComPtr<IArchiveGetRootProps> GetRootProps; 281 282 CArcErrorInfo ErrorInfo; // for OK archives 283 CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN) 284 285 UString Path; 286 UString filePath; 287 UString DefaultName; 288 int FormatIndex; // - 1 means Parser. 289 int SubfileIndex; 290 FILETIME MTime; 291 bool MTimeDefined; 292 293 Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler 294 UInt64 PhySize; 295 // UInt64 OkPhySize; 296 bool PhySizeDefined; 297 // bool OkPhySize_Defined; 298 UInt64 FileSize; 299 UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file 300 // bool offsetDefined; 301 GetEstmatedPhySize()302 UInt64 GetEstmatedPhySize() const { return PhySizeDefined ? PhySize : FileSize; } 303 304 UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler GetGlobalOffset()305 Int64 GetGlobalOffset() const { return ArcStreamOffset + Offset; } // it's global offset of archive 306 307 // AString ErrorFlagsText; 308 309 bool IsParseArc; 310 311 bool IsTree; 312 bool IsReadOnly; 313 314 bool Ask_Deleted; 315 bool Ask_AltStream; 316 bool Ask_Aux; 317 bool Ask_INode; 318 319 bool IgnoreSplit; // don't try split handler 320 321 // void Set_ErrorFlagsText(); 322 CArc()323 CArc(): 324 MTimeDefined(false), 325 IsTree(false), 326 IsReadOnly(false), 327 Ask_Deleted(false), 328 Ask_AltStream(false), 329 Ask_Aux(false), 330 Ask_INode(false), 331 IgnoreSplit(false) 332 {} 333 334 HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes); 335 336 // ~CArc(); 337 Close()338 HRESULT Close() 339 { 340 InStream.Release(); 341 return Archive->Close(); 342 } 343 344 HRESULT GetItemPath(UInt32 index, UString &result) const; 345 HRESULT GetDefaultItemPath(UInt32 index, UString &result) const; 346 347 // GetItemPath2 adds [DELETED] dir prefix for deleted items. 348 HRESULT GetItemPath2(UInt32 index, UString &result) const; 349 350 HRESULT GetItem(UInt32 index, CReadArcItem &item) const; 351 352 HRESULT GetItemSize(UInt32 index, UInt64 &size, bool &defined) const; 353 HRESULT GetItemMTime(UInt32 index, FILETIME &ft, bool &defined) const; IsItemAnti(UInt32 index,bool & result)354 HRESULT IsItemAnti(UInt32 index, bool &result) const 355 { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); } 356 357 358 HRESULT OpenStream(const COpenOptions &options); 359 HRESULT OpenStreamOrFile(COpenOptions &options); 360 361 HRESULT ReOpen(const COpenOptions &options); 362 363 HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream); 364 }; 365 366 struct CArchiveLink 367 { 368 CObjectVector<CArc> Arcs; 369 UStringVector VolumePaths; 370 UInt64 VolumesSize; 371 bool IsOpen; 372 373 bool PasswordWasAsked; 374 // UString Password; 375 376 // int NonOpenErrorFormatIndex; // - 1 means no Error. 377 UString NonOpen_ArcPath; 378 379 CArcErrorInfo NonOpen_ErrorInfo; 380 381 // UString ErrorsText; 382 // void Set_ErrorsText(); 383 CArchiveLinkCArchiveLink384 CArchiveLink(): 385 VolumesSize(0), 386 IsOpen(false), 387 PasswordWasAsked(false) 388 {} 389 390 void KeepModeForNextOpen(); 391 HRESULT Close(); 392 void Release(); ~CArchiveLinkCArchiveLink393 ~CArchiveLink() { Release(); } 394 GetArcCArchiveLink395 const CArc *GetArc() const { return &Arcs.Back(); } GetArchiveCArchiveLink396 IInArchive *GetArchive() const { return Arcs.Back().Archive; } GetArchiveGetRawPropsCArchiveLink397 IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; } GetArchiveGetRootPropsCArchiveLink398 IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; } 399 400 HRESULT Open(COpenOptions &options); 401 HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI); 402 HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI); 403 Open_StrictCArchiveLink404 HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI) 405 { 406 HRESULT result = Open3(options, callbackUI); 407 if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0) 408 result = S_FALSE; 409 return result; 410 } 411 412 HRESULT ReOpen(COpenOptions &options); 413 }; 414 415 bool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types); 416 417 #endif 418