1 // ICoder.h
2 
3 #ifndef __ICODER_H
4 #define __ICODER_H
5 
6 #include "IStream.h"
7 
8 #define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x)
9 
10 CODER_INTERFACE(ICompressProgressInfo, 0x04)
11 {
12   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE;
13 
14   /* (inSize) can be NULL, if unknown
15      (outSize) can be NULL, if unknown
16 
17   returns:
18     S_OK
19     E_ABORT  : Break by user
20     another error codes
21   */
22 };
23 
24 CODER_INTERFACE(ICompressCoder, 0x05)
25 {
26   STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
27       const UInt64 *inSize, const UInt64 *outSize,
28       ICompressProgressInfo *progress) PURE;
29 };
30 
31 CODER_INTERFACE(ICompressCoder2, 0x18)
32 {
33   STDMETHOD(Code)(ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,
34       ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,
35       ICompressProgressInfo *progress) PURE;
36 };
37 
38 /*
39   ICompressCoder::Code
40   ICompressCoder2::Code
41 
42   returns:
43     S_OK     : OK
44     S_FALSE  : data error (for decoders)
45     E_OUTOFMEMORY : memory allocation error
46     E_NOTIMPL : unsupported encoding method (for decoders)
47     another error code : some error. For example, it can be error code received from inStream or outStream function.
48 
49   Parameters:
50     (inStream != NULL)
51     (outStream != NULL)
52 
53     if (inSize != NULL)
54     {
55       Encoders in 7-Zip ignore (inSize).
56       Decoder can use (*inSize) to check that stream was decoded correctly.
57       Some decoder in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode)
58     }
59 
60     If it's required to limit the reading from input stream (inStream), it can
61       be done with ISequentialInStream implementation.
62 
63     if (outSize != NULL)
64     {
65       Encoders in 7-Zip ignore (outSize).
66       Decoder unpacks no more than (*outSize) bytes.
67     }
68 
69     (progress == NULL) is allowed.
70 
71 
72   Decoding with Code() function
73   -----------------------------
74 
75   You can request some interfaces before decoding
76    - ICompressSetDecoderProperties2
77    - ICompressSetFinishMode
78 
79   If you need to decode full stream:
80   {
81     1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1);
82     2) call the Code() function with specified (inSize) and (outSize), if these sizes are known.
83   }
84 
85   If you need to decode only part of stream:
86   {
87     1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0);
88     2) Call the Code() function with specified (inSize = NULL) and specified (outSize).
89   }
90 
91   Encoding with Code() function
92   -----------------------------
93 
94   You can request some interfaces :
95   - ICompressSetCoderProperties   - use it before encoding to set properties
96   - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties.
97 
98   ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1)
99      The rules are similar to ICompressCoder rules
100 */
101 
102 
103 namespace NCoderPropID
104 {
105   enum EEnum
106   {
107     kDefaultProp = 0,
108     kDictionarySize,    // VT_UI4
109     kUsedMemorySize,    // VT_UI4
110     kOrder,             // VT_UI4
111     kBlockSize,         // VT_UI4 or VT_UI8
112     kPosStateBits,      // VT_UI4
113     kLitContextBits,    // VT_UI4
114     kLitPosBits,        // VT_UI4
115     kNumFastBytes,      // VT_UI4
116     kMatchFinder,       // VT_BSTR
117     kMatchFinderCycles, // VT_UI4
118     kNumPasses,         // VT_UI4
119     kAlgorithm,         // VT_UI4
120     kNumThreads,        // VT_UI4
121     kEndMarker,         // VT_BOOL
122     kLevel,             // VT_UI4
123     kReduceSize,        // VT_UI8 : it's estimated size of largest data stream that will be compressed
124                         //   encoder can use this value to reduce dictionary size and allocate data buffers
125 
126     kExpectedDataSize,  // VT_UI8 : for ICompressSetCoderPropertiesOpt :
127                         //   it's estimated size of current data stream
128                         //   real data size can differ from that size
129                         //   encoder can use this value to optimize encoder initialization
130 
131     kBlockSize2,        // VT_UI4 or VT_UI8
132     kCheckSize,         // VT_UI4 : size of digest in bytes
133     kFilter,            // VT_BSTR
134     kMemUse,            // VT_UI8
135     kAffinity           // VT_UI8
136   };
137 }
138 
139 CODER_INTERFACE(ICompressSetCoderPropertiesOpt, 0x1F)
140 {
141   STDMETHOD(SetCoderPropertiesOpt)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
142 };
143 
144 CODER_INTERFACE(ICompressSetCoderProperties, 0x20)
145 {
146   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE;
147 };
148 
149 /*
150 CODER_INTERFACE(ICompressSetCoderProperties, 0x21)
151 {
152   STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE;
153 };
154 */
155 
156 CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22)
157 {
158   /* returns:
159     S_OK
160     E_NOTIMP      : unsupported properties
161     E_INVALIDARG  : incorrect (or unsupported) properties
162     E_OUTOFMEMORY : memory allocation error
163   */
164   STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE;
165 };
166 
167 CODER_INTERFACE(ICompressWriteCoderProperties, 0x23)
168 {
169   STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE;
170 };
171 
172 CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24)
173 {
174   STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE;
175 };
176 
177 CODER_INTERFACE(ICompressSetCoderMt, 0x25)
178 {
179   STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE;
180 };
181 
182 CODER_INTERFACE(ICompressSetFinishMode, 0x26)
183 {
184   STDMETHOD(SetFinishMode)(UInt32 finishMode) PURE;
185 
186   /* finishMode:
187     0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined.
188     1 : full decoding. The stream must be finished at the end of decoding. */
189 };
190 
191 CODER_INTERFACE(ICompressGetInStreamProcessedSize2, 0x27)
192 {
193   STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value) PURE;
194 };
195 
196 CODER_INTERFACE(ICompressSetMemLimit, 0x28)
197 {
198   STDMETHOD(SetMemLimit)(UInt64 memUsage) PURE;
199 };
200 
201 
202 /*
203   ICompressReadUnusedFromInBuf is supported by ICoder object
204   call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...).
205   ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed
206   to read from inStream to internal buffers more data than minimal data required for decoding.
207   So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input
208   data from the internal buffer.
209   in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code().
210 */
211 
212 CODER_INTERFACE(ICompressReadUnusedFromInBuf, 0x29)
213 {
214   STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize) PURE;
215 };
216 
217 
218 
219 CODER_INTERFACE(ICompressGetSubStreamSize, 0x30)
220 {
221   STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE;
222 
223   /* returns:
224     S_OK     : (*value) contains the size or estimated size (can be incorrect size)
225     S_FALSE  : size is undefined
226     E_NOTIMP : the feature is not implemented
227 
228   Let's (read_size) is size of data that was already read by ISequentialInStream::Read().
229   The caller should call GetSubStreamSize() after each Read() and check sizes:
230     if (start_of_subStream + *value < read_size)
231     {
232       // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream:
233       start_of_subStream += *value;
234       subStream++;
235     }
236   */
237 };
238 
239 CODER_INTERFACE(ICompressSetInStream, 0x31)
240 {
241   STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE;
242   STDMETHOD(ReleaseInStream)() PURE;
243 };
244 
245 CODER_INTERFACE(ICompressSetOutStream, 0x32)
246 {
247   STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE;
248   STDMETHOD(ReleaseOutStream)() PURE;
249 };
250 
251 /*
252 CODER_INTERFACE(ICompressSetInStreamSize, 0x33)
253 {
254   STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE;
255 };
256 */
257 
258 CODER_INTERFACE(ICompressSetOutStreamSize, 0x34)
259 {
260   STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE;
261 
262   /* That function initializes decoder structures.
263      Call this function only for stream version of decoder.
264        if (outSize == NULL), then output size is unknown
265        if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */
266 };
267 
268 CODER_INTERFACE(ICompressSetBufSize, 0x35)
269 {
270   STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE;
271   STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE;
272 };
273 
274 CODER_INTERFACE(ICompressInitEncoder, 0x36)
275 {
276   STDMETHOD(InitEncoder)() PURE;
277 
278   /* That function initializes encoder structures.
279      Call this function only for stream version of encoder. */
280 };
281 
282 CODER_INTERFACE(ICompressSetInStream2, 0x37)
283 {
284   STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream) PURE;
285   STDMETHOD(ReleaseInStream2)(UInt32 streamIndex) PURE;
286 };
287 
288 /*
289 CODER_INTERFACE(ICompressSetOutStream2, 0x38)
290 {
291   STDMETHOD(SetOutStream2)(UInt32 streamIndex, ISequentialOutStream *outStream) PURE;
292   STDMETHOD(ReleaseOutStream2)(UInt32 streamIndex) PURE;
293 };
294 
295 CODER_INTERFACE(ICompressSetInStreamSize2, 0x39)
296 {
297   STDMETHOD(SetInStreamSize2)(UInt32 streamIndex, const UInt64 *inSize) PURE;
298 };
299 */
300 
301 
302 /*
303   ICompressFilter
304   Filter() converts as most as possible bytes required for fast processing.
305      Some filters have (smallest_fast_block).
306      For example, (smallest_fast_block == 16) for AES CBC/CTR filters.
307      If data stream is not finished, caller must call Filter() for larger block:
308      where (size >= smallest_fast_block).
309      if (size >= smallest_fast_block)
310      {
311        The filter can leave some bytes at the end of data without conversion:
312        if there are data alignment reasons or speed reasons.
313        The caller must read additional data from stream and call Filter() again.
314      }
315      If data stream was finished, caller can call Filter() for (size < smallest_fast_block)
316 
317      data : must be aligned for at least 16 bytes for some filters (AES)
318 
319      returns: (outSize):
320        if (outSize == 0) : Filter have not converted anything.
321            So the caller can stop processing, if data stream was finished.
322        if (outSize <= size) : Filter have converted outSize bytes
323        if (outSize >  size) : Filter have not converted anything.
324            and it needs at least outSize bytes to convert one block
325            (it's for crypto block algorithms).
326 */
327 
328 #define INTERFACE_ICompressFilter(x) \
329   STDMETHOD(Init)() x; \
330   STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) x; \
331 
332 CODER_INTERFACE(ICompressFilter, 0x40)
333 {
334   INTERFACE_ICompressFilter(PURE);
335 };
336 
337 
338 CODER_INTERFACE(ICompressCodecsInfo, 0x60)
339 {
340   STDMETHOD(GetNumMethods)(UInt32 *numMethods) PURE;
341   STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
342   STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE;
343   STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE;
344 };
345 
346 CODER_INTERFACE(ISetCompressCodecsInfo, 0x61)
347 {
348   STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE;
349 };
350 
351 CODER_INTERFACE(ICryptoProperties, 0x80)
352 {
353   STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE;
354   STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE;
355 };
356 
357 /*
358 CODER_INTERFACE(ICryptoResetSalt, 0x88)
359 {
360   STDMETHOD(ResetSalt)() PURE;
361 };
362 */
363 
364 CODER_INTERFACE(ICryptoResetInitVector, 0x8C)
365 {
366   STDMETHOD(ResetInitVector)() PURE;
367 
368   /* Call ResetInitVector() only for encoding.
369      Call ResetInitVector() before encoding and before WriteCoderProperties().
370      Crypto encoder can create random IV in that function. */
371 };
372 
373 CODER_INTERFACE(ICryptoSetPassword, 0x90)
374 {
375   STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE;
376 };
377 
378 CODER_INTERFACE(ICryptoSetCRC, 0xA0)
379 {
380   STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE;
381 };
382 
383 
384 namespace NMethodPropID
385 {
386   enum EEnum
387   {
388     kID,
389     kName,
390     kDecoder,
391     kEncoder,
392     kPackStreams,
393     kUnpackStreams,
394     kDescription,
395     kDecoderIsAssigned,
396     kEncoderIsAssigned,
397     kDigestSize,
398     kIsFilter
399   };
400 }
401 
402 
403 #define INTERFACE_IHasher(x) \
404   STDMETHOD_(void, Init)() throw() x; \
405   STDMETHOD_(void, Update)(const void *data, UInt32 size) throw() x; \
406   STDMETHOD_(void, Final)(Byte *digest) throw() x; \
407   STDMETHOD_(UInt32, GetDigestSize)() throw() x; \
408 
409 CODER_INTERFACE(IHasher, 0xC0)
410 {
411   INTERFACE_IHasher(PURE)
412 };
413 
414 CODER_INTERFACE(IHashers, 0xC1)
415 {
416   STDMETHOD_(UInt32, GetNumHashers)() PURE;
417   STDMETHOD(GetHasherProp)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
418   STDMETHOD(CreateHasher)(UInt32 index, IHasher **hasher) PURE;
419 };
420 
421 extern "C"
422 {
423   typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);
424   typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
425   typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject);
426   typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject);
427 
428   typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);
429 
430   typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo);
431 }
432 
433 #endif
434