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