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