• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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