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