1 // IArchive.h 2 3 #ifndef __IARCHIVE_H 4 #define __IARCHIVE_H 5 6 #include "../IProgress.h" 7 #include "../IStream.h" 8 #include "../PropID.h" 9 10 #define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) 11 #define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) 12 13 /* 14 How the function in 7-Zip returns object for output parameter via pointer 15 16 1) The caller sets the value of variable before function call: 17 PROPVARIANT : vt = VT_EMPTY 18 BSTR : NULL 19 IUnknown* and derived interfaces : NULL 20 another scalar types : any non-initialized value is allowed 21 22 2) The callee in current 7-Zip code now can free input object for output parameter: 23 PROPVARIANT : the callee calls VariantClear(propvaiant_ptr) for input 24 value stored in variable 25 another types : the callee ignores stored value. 26 27 3) The callee writes new value to variable for output parameter and 28 returns execution to caller. 29 30 4) The caller must free or release object returned by the callee: 31 PROPVARIANT : VariantClear(&propvaiant) 32 BSTR : SysFreeString(bstr) 33 IUnknown* and derived interfaces : if (ptr) ptr->Relase() 34 */ 35 36 37 namespace NFileTimeType 38 { 39 enum EEnum 40 { 41 kNotDefined = -1, 42 kWindows = 0, 43 kUnix, 44 kDOS, 45 k1ns 46 }; 47 } 48 49 namespace NArcInfoFlags 50 { 51 const UInt32 kKeepName = 1 << 0; // keep name of file in archive name 52 const UInt32 kAltStreams = 1 << 1; // the handler supports alt streams 53 const UInt32 kNtSecure = 1 << 2; // the handler supports NT security 54 const UInt32 kFindSignature = 1 << 3; // the handler can find start of archive 55 const UInt32 kMultiSignature = 1 << 4; // there are several signatures 56 const UInt32 kUseGlobalOffset = 1 << 5; // the seek position of stream must be set as global offset 57 const UInt32 kStartOpen = 1 << 6; // call handler for each start position 58 const UInt32 kPureStartOpen = 1 << 7; // call handler only for start of file 59 const UInt32 kBackwardOpen = 1 << 8; // archive can be open backward 60 const UInt32 kPreArc = 1 << 9; // such archive can be stored before real archive (like SFX stub) 61 const UInt32 kSymLinks = 1 << 10; // the handler supports symbolic links 62 const UInt32 kHardLinks = 1 << 11; // the handler supports hard links 63 const UInt32 kByExtOnlyOpen = 1 << 12; // call handler only if file extension matches 64 const UInt32 kHashHandler = 1 << 13; // the handler contains the hashes (checksums) 65 const UInt32 kCTime = 1 << 14; 66 const UInt32 kCTime_Default = 1 << 15; 67 const UInt32 kATime = 1 << 16; 68 const UInt32 kATime_Default = 1 << 17; 69 const UInt32 kMTime = 1 << 18; 70 const UInt32 kMTime_Default = 1 << 19; 71 // const UInt32 kTTime_Reserved = 1 << 20; 72 // const UInt32 kTTime_Reserved_Default = 1 << 21; 73 } 74 75 namespace NArcInfoTimeFlags 76 { 77 const unsigned kTime_Prec_Mask_bit_index = 0; 78 const unsigned kTime_Prec_Mask_num_bits = 26; 79 80 const unsigned kTime_Prec_Default_bit_index = 27; 81 const unsigned kTime_Prec_Default_num_bits = 5; 82 } 83 84 #define TIME_PREC_TO_ARC_FLAGS_MASK(x) \ 85 ((UInt32)1 << (NArcInfoTimeFlags::kTime_Prec_Mask_bit_index + (x))) 86 87 #define TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(x) \ 88 ((UInt32)(x) << NArcInfoTimeFlags::kTime_Prec_Default_bit_index) 89 90 namespace NArchive 91 { 92 namespace NHandlerPropID 93 { 94 enum 95 { 96 kName = 0, // VT_BSTR 97 kClassID, // binary GUID in VT_BSTR 98 kExtension, // VT_BSTR 99 kAddExtension, // VT_BSTR 100 kUpdate, // VT_BOOL 101 kKeepName, // VT_BOOL 102 kSignature, // binary in VT_BSTR 103 kMultiSignature, // binary in VT_BSTR 104 kSignatureOffset, // VT_UI4 105 kAltStreams, // VT_BOOL 106 kNtSecure, // VT_BOOL 107 kFlags, // VT_UI4 108 kTimeFlags // VT_UI4 109 }; 110 } 111 112 namespace NExtract 113 { 114 namespace NAskMode 115 { 116 enum 117 { 118 kExtract = 0, 119 kTest, 120 kSkip, 121 kReadExternal 122 }; 123 } 124 125 namespace NOperationResult 126 { 127 enum 128 { 129 kOK = 0, 130 kUnsupportedMethod, 131 kDataError, 132 kCRCError, 133 kUnavailable, 134 kUnexpectedEnd, 135 kDataAfterEnd, 136 kIsNotArc, 137 kHeadersError, 138 kWrongPassword 139 }; 140 } 141 } 142 143 namespace NEventIndexType 144 { 145 enum 146 { 147 kNoIndex = 0, 148 kInArcIndex, 149 kBlockIndex, 150 kOutArcIndex 151 // kArcProp 152 }; 153 } 154 155 namespace NUpdate 156 { 157 namespace NOperationResult 158 { 159 enum 160 { 161 kOK = 0 162 // kError = 1, 163 // kError_FileChanged 164 }; 165 } 166 } 167 } 168 169 #define INTERFACE_IArchiveOpenCallback(x) \ 170 STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ 171 STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ 172 173 ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) 174 { 175 INTERFACE_IArchiveOpenCallback(PURE); 176 }; 177 178 /* 179 IArchiveExtractCallback:: 180 181 7-Zip doesn't call IArchiveExtractCallback functions 182 GetStream() 183 PrepareOperation() 184 SetOperationResult() 185 from different threads simultaneously. 186 But 7-Zip can call functions for IProgress or ICompressProgressInfo functions 187 from another threads simultaneously with calls for IArchiveExtractCallback interface. 188 189 IArchiveExtractCallback::GetStream() 190 UInt32 index - index of item in Archive 191 Int32 askExtractMode (Extract::NAskMode) 192 if (askMode != NExtract::NAskMode::kExtract) 193 { 194 then the callee doesn't write data to stream: (*outStream == NULL) 195 } 196 197 Out: 198 (*outStream == NULL) - for directories 199 (*outStream == NULL) - if link (hard link or symbolic link) was created 200 if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract) 201 { 202 then the caller must skip extracting of that file. 203 } 204 205 returns: 206 S_OK : OK 207 S_FALSE : data error (for decoders) 208 209 if (IProgress::SetTotal() was called) 210 { 211 IProgress::SetCompleted(completeValue) uses 212 packSize - for some stream formats (xz, gz, bz2, lzma, z, ppmd). 213 unpackSize - for another formats. 214 } 215 else 216 { 217 IProgress::SetCompleted(completeValue) uses packSize. 218 } 219 220 SetOperationResult() 221 7-Zip calls SetOperationResult at the end of extracting, 222 so the callee can close the file, set attributes, timestamps and security information. 223 224 Int32 opRes (NExtract::NOperationResult) 225 */ 226 227 #define INTERFACE_IArchiveExtractCallback(x) \ 228 INTERFACE_IProgress(x) \ 229 STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ 230 STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ 231 STDMETHOD(SetOperationResult)(Int32 opRes) x; \ 232 233 ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) 234 { 235 INTERFACE_IArchiveExtractCallback(PURE) 236 }; 237 238 239 240 /* 241 IArchiveExtractCallbackMessage can be requested from IArchiveExtractCallback object 242 by Extract() or UpdateItems() functions to report about extracting errors 243 ReportExtractResult() 244 UInt32 indexType (NEventIndexType) 245 UInt32 index 246 Int32 opRes (NExtract::NOperationResult) 247 */ 248 249 #define INTERFACE_IArchiveExtractCallbackMessage(x) \ 250 STDMETHOD(ReportExtractResult)(UInt32 indexType, UInt32 index, Int32 opRes) x; \ 251 252 ARCHIVE_INTERFACE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21) 253 { 254 INTERFACE_IArchiveExtractCallbackMessage(PURE) 255 }; 256 257 258 #define INTERFACE_IArchiveOpenVolumeCallback(x) \ 259 STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ 260 STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ 261 262 ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) 263 { 264 INTERFACE_IArchiveOpenVolumeCallback(PURE); 265 }; 266 267 268 ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) 269 { 270 STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; 271 }; 272 273 274 ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) 275 { 276 STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; 277 }; 278 279 280 /* 281 IInArchive::Open 282 stream 283 if (kUseGlobalOffset), stream current position can be non 0. 284 if (!kUseGlobalOffset), stream current position is 0. 285 if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream 286 if (*maxCheckStartPosition == 0), the handler must check only current position as archive start 287 288 IInArchive::Extract: 289 indices must be sorted 290 numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means "all files" 291 testMode != 0 means "test files without writing to outStream" 292 293 IInArchive::GetArchiveProperty: 294 kpidOffset - start offset of archive. 295 VT_EMPTY : means offset = 0. 296 VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed 297 kpidPhySize - size of archive. VT_EMPTY means unknown size. 298 kpidPhySize is allowed to be larger than file size. In that case it must show 299 supposed size. 300 301 kpidIsDeleted: 302 kpidIsAltStream: 303 kpidIsAux: 304 kpidINode: 305 must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty. 306 307 308 Notes: 309 Don't call IInArchive functions for same IInArchive object from different threads simultaneously. 310 Some IInArchive handlers will work incorrectly in that case. 311 */ 312 313 #ifdef _MSC_VER 314 #define MY_NO_THROW_DECL_ONLY throw() 315 #else 316 #define MY_NO_THROW_DECL_ONLY 317 #endif 318 319 #define INTERFACE_IInArchive(x) \ 320 STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback) MY_NO_THROW_DECL_ONLY x; \ 321 STDMETHOD(Close)() MY_NO_THROW_DECL_ONLY x; \ 322 STDMETHOD(GetNumberOfItems)(UInt32 *numItems) MY_NO_THROW_DECL_ONLY x; \ 323 STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ 324 STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) MY_NO_THROW_DECL_ONLY x; \ 325 STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) MY_NO_THROW_DECL_ONLY x; \ 326 STDMETHOD(GetNumberOfProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ 327 STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ 328 STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProps) MY_NO_THROW_DECL_ONLY x; \ 329 STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) MY_NO_THROW_DECL_ONLY x; \ 330 331 ARCHIVE_INTERFACE(IInArchive, 0x60) 332 { 333 INTERFACE_IInArchive(PURE) 334 }; 335 336 namespace NParentType 337 { 338 enum 339 { 340 kDir = 0, 341 kAltStream 342 }; 343 }; 344 345 namespace NPropDataType 346 { 347 const UInt32 kMask_ZeroEnd = 1 << 4; 348 // const UInt32 kMask_BigEndian = 1 << 5; 349 const UInt32 kMask_Utf = 1 << 6; 350 const UInt32 kMask_Utf8 = kMask_Utf | 0; 351 const UInt32 kMask_Utf16 = kMask_Utf | 1; 352 // const UInt32 kMask_Utf32 = kMask_Utf | 2; 353 354 const UInt32 kNotDefined = 0; 355 const UInt32 kRaw = 1; 356 357 const UInt32 kUtf8z = kMask_Utf8 | kMask_ZeroEnd; 358 const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd; 359 }; 360 361 // UTF string (pointer to wchar_t) with zero end and little-endian. 362 #define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1)) 363 364 /* 365 GetRawProp: 366 Result: 367 S_OK - even if property is not set 368 */ 369 370 #define INTERFACE_IArchiveGetRawProps(x) \ 371 STDMETHOD(GetParent)(UInt32 index, UInt32 *parent, UInt32 *parentType) x; \ 372 STDMETHOD(GetRawProp)(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ 373 STDMETHOD(GetNumRawProps)(UInt32 *numProps) x; \ 374 STDMETHOD(GetRawPropInfo)(UInt32 index, BSTR *name, PROPID *propID) x; 375 376 ARCHIVE_INTERFACE(IArchiveGetRawProps, 0x70) 377 { 378 INTERFACE_IArchiveGetRawProps(PURE) 379 }; 380 381 #define INTERFACE_IArchiveGetRootProps(x) \ 382 STDMETHOD(GetRootProp)(PROPID propID, PROPVARIANT *value) x; \ 383 STDMETHOD(GetRootRawProp)(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType) x; \ 384 385 ARCHIVE_INTERFACE(IArchiveGetRootProps, 0x71) 386 { 387 INTERFACE_IArchiveGetRootProps(PURE) 388 }; 389 390 ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) 391 { 392 STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; 393 }; 394 395 /* 396 OpenForSize 397 Result: 398 S_FALSE - is not archive 399 ? - DATA error 400 */ 401 402 /* 403 const UInt32 kOpenFlags_RealPhySize = 1 << 0; 404 const UInt32 kOpenFlags_NoSeek = 1 << 1; 405 // const UInt32 kOpenFlags_BeforeExtract = 1 << 2; 406 */ 407 408 /* 409 Flags: 410 0 - opens archive with IInStream, if IInStream interface is supported 411 - if phySize is not available, it doesn't try to make full parse to get phySize 412 kOpenFlags_NoSeek - ArcOpen2 function doesn't use IInStream interface, even if it's available 413 kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file 414 415 if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified, 416 the handler can return S_OK, but it doesn't check even Signature. 417 So next Extract can be called for that sequential stream. 418 */ 419 420 /* 421 ARCHIVE_INTERFACE(IArchiveOpen2, 0x62) 422 { 423 STDMETHOD(ArcOpen2)(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback) PURE; 424 }; 425 */ 426 427 // ---------- UPDATE ---------- 428 429 /* 430 GetUpdateItemInfo outs: 431 *newData *newProps 432 0 0 - Copy data and properties from archive 433 0 1 - Copy data from archive, request new properties 434 1 0 - that combination is unused now 435 1 1 - Request new data and new properties. It can be used even for folders 436 437 indexInArchive = -1 if there is no item in archive, or if it doesn't matter. 438 439 440 GetStream out: 441 Result: 442 S_OK: 443 (*inStream == NULL) - only for directories 444 - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file 445 (*inStream != NULL) - for any file, even for empty file or anti-file 446 S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason) 447 (*inStream == NULL) 448 449 The order of calling for hard links: 450 - GetStream() 451 - GetProperty(kpidHardLink) 452 453 SetOperationResult() 454 Int32 opRes (NExtract::NOperationResult::kOK) 455 */ 456 457 #define INTERFACE_IArchiveUpdateCallback(x) \ 458 INTERFACE_IProgress(x); \ 459 STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive) x; \ 460 STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ 461 STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ 462 STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ 463 464 ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) 465 { 466 INTERFACE_IArchiveUpdateCallback(PURE); 467 }; 468 469 #define INTERFACE_IArchiveUpdateCallback2(x) \ 470 INTERFACE_IArchiveUpdateCallback(x) \ 471 STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ 472 STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ 473 474 ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) 475 { 476 INTERFACE_IArchiveUpdateCallback2(PURE); 477 }; 478 479 namespace NUpdateNotifyOp 480 { 481 enum 482 { 483 kAdd = 0, 484 kUpdate, 485 kAnalyze, 486 kReplicate, 487 kRepack, 488 kSkip, 489 kDelete, 490 kHeader, 491 kHashRead, 492 kInFileChanged 493 // , kOpFinished 494 // , kNumDefined 495 }; 496 }; 497 498 /* 499 IArchiveUpdateCallbackFile::ReportOperation 500 UInt32 indexType (NEventIndexType) 501 UInt32 index 502 UInt32 notifyOp (NUpdateNotifyOp) 503 */ 504 505 #define INTERFACE_IArchiveUpdateCallbackFile(x) \ 506 STDMETHOD(GetStream2)(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp) x; \ 507 STDMETHOD(ReportOperation)(UInt32 indexType, UInt32 index, UInt32 notifyOp) x; \ 508 509 ARCHIVE_INTERFACE(IArchiveUpdateCallbackFile, 0x83) 510 { 511 INTERFACE_IArchiveUpdateCallbackFile(PURE); 512 }; 513 514 515 #define INTERFACE_IArchiveGetDiskProperty(x) \ 516 STDMETHOD(GetDiskProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ 517 518 ARCHIVE_INTERFACE(IArchiveGetDiskProperty, 0x84) 519 { 520 INTERFACE_IArchiveGetDiskProperty(PURE); 521 }; 522 523 /* 524 #define INTERFACE_IArchiveUpdateCallbackArcProp(x) \ 525 STDMETHOD(ReportProp)(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x; \ 526 STDMETHOD(ReportRawProp)(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x; \ 527 STDMETHOD(ReportFinished)(UInt32 indexType, UInt32 index, Int32 opRes) x; \ 528 STDMETHOD(DoNeedArcProp)(PROPID propID, Int32 *answer) x; \ 529 530 531 ARCHIVE_INTERFACE(IArchiveUpdateCallbackArcProp, 0x85) 532 { 533 INTERFACE_IArchiveUpdateCallbackArcProp(PURE); 534 }; 535 */ 536 537 /* 538 UpdateItems() 539 ------------- 540 541 outStream: output stream. (the handler) MUST support the case when 542 Seek position in outStream is not ZERO. 543 but the caller calls with empty outStream and seek position is ZERO?? 544 545 archives with stub: 546 547 If archive is open and the handler and (Offset > 0), then the handler 548 knows about stub size. 549 UpdateItems(): 550 1) the handler MUST copy that stub to outStream 551 2) the caller MUST NOT copy the stub to outStream, if 552 "rsfx" property is set with SetProperties 553 554 the handler must support the case where 555 ISequentialOutStream *outStream 556 */ 557 558 559 #define INTERFACE_IOutArchive(x) \ 560 STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ 561 STDMETHOD(GetFileTimeType)(UInt32 *type) x; 562 563 ARCHIVE_INTERFACE(IOutArchive, 0xA0) 564 { 565 INTERFACE_IOutArchive(PURE) 566 }; 567 568 569 /* 570 ISetProperties::SetProperties() 571 PROPVARIANT values[i].vt: 572 VT_EMPTY 573 VT_BOOL 574 VT_UI4 - if 32-bit number 575 VT_UI8 - if 64-bit number 576 VT_BSTR 577 */ 578 579 ARCHIVE_INTERFACE(ISetProperties, 0x03) 580 { 581 STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) PURE; 582 }; 583 584 ARCHIVE_INTERFACE(IArchiveKeepModeForNextOpen, 0x04) 585 { 586 STDMETHOD(KeepModeForNextOpen)() PURE; 587 }; 588 589 /* Exe handler: the handler for executable format (PE, ELF, Mach-O). 590 SFX archive: executable stub + some tail data. 591 before 9.31: exe handler didn't parse SFX archives as executable format. 592 for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */ 593 594 ARCHIVE_INTERFACE(IArchiveAllowTail, 0x05) 595 { 596 STDMETHOD(AllowTail)(Int32 allowTail) PURE; 597 }; 598 599 600 #define IMP_IInArchive_GetProp(k) \ 601 (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ 602 { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ 603 *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \ 604 605 606 struct CStatProp 607 { 608 const char *Name; 609 UInt32 PropID; 610 VARTYPE vt; 611 }; 612 613 namespace NWindows { 614 namespace NCOM { 615 // PropVariant.cpp 616 BSTR AllocBstrFromAscii(const char *s) throw(); 617 }} 618 619 #define IMP_IInArchive_GetProp_WITH_NAME(k) \ 620 (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ 621 { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \ 622 const CStatProp &prop = k[index]; \ 623 *propID = (PROPID)prop.PropID; *varType = prop.vt; \ 624 *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \ 625 626 #define IMP_IInArchive_Props \ 627 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ 628 { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ 629 STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) 630 631 #define IMP_IInArchive_Props_WITH_NAME \ 632 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProps) \ 633 { *numProps = ARRAY_SIZE(kProps); return S_OK; } \ 634 STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) 635 636 637 #define IMP_IInArchive_ArcProps \ 638 STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ 639 { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ 640 STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) 641 642 #define IMP_IInArchive_ArcProps_WITH_NAME \ 643 STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ 644 { *numProps = ARRAY_SIZE(kArcProps); return S_OK; } \ 645 STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) 646 647 #define IMP_IInArchive_ArcProps_NO_Table \ 648 STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProps) \ 649 { *numProps = 0; return S_OK; } \ 650 STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ 651 { return E_NOTIMPL; } \ 652 653 #define IMP_IInArchive_ArcProps_NO \ 654 IMP_IInArchive_ArcProps_NO_Table \ 655 STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ 656 { value->vt = VT_EMPTY; return S_OK; } 657 658 659 660 #define k_IsArc_Res_NO 0 661 #define k_IsArc_Res_YES 1 662 #define k_IsArc_Res_NEED_MORE 2 663 // #define k_IsArc_Res_YES_LOW_PROB 3 664 665 #define API_FUNC_IsArc EXTERN_C UInt32 WINAPI 666 #define API_FUNC_static_IsArc extern "C" { static UInt32 WINAPI 667 668 extern "C" 669 { 670 typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject); 671 672 typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size); 673 typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc); 674 675 typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats); 676 typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value); 677 typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value); 678 679 typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive); 680 typedef HRESULT (WINAPI *Func_SetLargePageMode)(); 681 // typedef HRESULT (WINAPI *Func_SetClientVersion)(UInt32 version); 682 683 typedef IOutArchive * (*Func_CreateOutArchive)(); 684 typedef IInArchive * (*Func_CreateInArchive)(); 685 } 686 687 688 /* 689 if there is no time in archive, external MTime of archive 690 will be used instead of _item.Time from archive. 691 For 7-zip before 22.00 we need to return some supported value. 692 But (kpidTimeType > kDOS) is not allowed in 7-Zip before 22.00. 693 So we return highest precision value supported by old 7-Zip. 694 new 7-Zip 22.00 doesn't use that value in usual cases. 695 */ 696 697 698 #define DECLARE_AND_SET_CLIENT_VERSION_VAR 699 #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ 700 NFileTimeType::kWindows 701 702 /* 703 extern UInt32 g_ClientVersion; 704 705 #define GET_CLIENT_VERSION(major, minor) \ 706 ((UInt32)(((UInt32)(major) << 16) | (UInt32)(minor))) 707 708 #define DECLARE_AND_SET_CLIENT_VERSION_VAR \ 709 UInt32 g_ClientVersion = GET_CLIENT_VERSION(MY_VER_MAJOR, MY_VER_MINOR); 710 711 #define GET_FileTimeType_NotDefined_for_GetFileTimeType \ 712 ((UInt32)(g_ClientVersion >= GET_CLIENT_VERSION(22, 0) ? \ 713 (UInt32)(Int32)NFileTimeType::kNotDefined : \ 714 NFileTimeType::kWindows)) 715 */ 716 717 #endif 718