1*f6dc9357SAndroid Build Coastguard Worker // IStream.h 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_ISTREAM_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_ISTREAM_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../Common/Common0.h" 7*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MyTypes.h" 8*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MyWindows.h" 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker #include "IDecl.h" 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker Z7_PURE_INTERFACES_BEGIN 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACE_CONSTR_STREAM_SUB(i, base, n) \ 15*f6dc9357SAndroid Build Coastguard Worker Z7_DECL_IFACE_7ZIP_SUB(i, base, 3, n) \ 16*f6dc9357SAndroid Build Coastguard Worker { Z7_IFACE_COM7_PURE(i) }; 17*f6dc9357SAndroid Build Coastguard Worker 18*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACE_CONSTR_STREAM(i, n) \ 19*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM_SUB(i, IUnknown, n) 20*f6dc9357SAndroid Build Coastguard Worker 21*f6dc9357SAndroid Build Coastguard Worker 22*f6dc9357SAndroid Build Coastguard Worker /* 23*f6dc9357SAndroid Build Coastguard Worker ISequentialInStream::Read() 24*f6dc9357SAndroid Build Coastguard Worker The requirement for caller: (processedSize != NULL). 25*f6dc9357SAndroid Build Coastguard Worker The callee can allow (processedSize == NULL) for compatibility reasons. 26*f6dc9357SAndroid Build Coastguard Worker 27*f6dc9357SAndroid Build Coastguard Worker if (size == 0), this function returns S_OK and (*processedSize) is set to 0. 28*f6dc9357SAndroid Build Coastguard Worker 29*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 30*f6dc9357SAndroid Build Coastguard Worker { 31*f6dc9357SAndroid Build Coastguard Worker Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size), 32*f6dc9357SAndroid Build Coastguard Worker where (avail_size) is the size of remaining bytes in stream. 33*f6dc9357SAndroid Build Coastguard Worker If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0). 34*f6dc9357SAndroid Build Coastguard Worker You must call Read() in loop, if you need to read exact amount of data. 35*f6dc9357SAndroid Build Coastguard Worker } 36*f6dc9357SAndroid Build Coastguard Worker 37*f6dc9357SAndroid Build Coastguard Worker If seek pointer before Read() call was changed to position past the end of stream: 38*f6dc9357SAndroid Build Coastguard Worker if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0. 39*f6dc9357SAndroid Build Coastguard Worker 40*f6dc9357SAndroid Build Coastguard Worker ERROR CASES: 41*f6dc9357SAndroid Build Coastguard Worker If the function returns error code, then (*processedSize) is size of 42*f6dc9357SAndroid Build Coastguard Worker data written to (data) buffer (it can be data before error or data with errors). 43*f6dc9357SAndroid Build Coastguard Worker The recommended way for callee to work with reading errors: 44*f6dc9357SAndroid Build Coastguard Worker 1) write part of data before error to (data) buffer and return S_OK. 45*f6dc9357SAndroid Build Coastguard Worker 2) return error code for further calls of Read(). 46*f6dc9357SAndroid Build Coastguard Worker */ 47*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_ISequentialInStream(x) \ 48*f6dc9357SAndroid Build Coastguard Worker x(Read(void *data, UInt32 size, UInt32 *processedSize)) 49*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(ISequentialInStream, 0x01) 50*f6dc9357SAndroid Build Coastguard Worker 51*f6dc9357SAndroid Build Coastguard Worker 52*f6dc9357SAndroid Build Coastguard Worker /* 53*f6dc9357SAndroid Build Coastguard Worker ISequentialOutStream::Write() 54*f6dc9357SAndroid Build Coastguard Worker The requirement for caller: (processedSize != NULL). 55*f6dc9357SAndroid Build Coastguard Worker The callee can allow (processedSize == NULL) for compatibility reasons. 56*f6dc9357SAndroid Build Coastguard Worker 57*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 58*f6dc9357SAndroid Build Coastguard Worker { 59*f6dc9357SAndroid Build Coastguard Worker Partial write is allowed: (*processedSize <= size), 60*f6dc9357SAndroid Build Coastguard Worker but this function must write at least 1 byte: (*processedSize > 0). 61*f6dc9357SAndroid Build Coastguard Worker You must call Write() in loop, if you need to write exact amount of data. 62*f6dc9357SAndroid Build Coastguard Worker } 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker ERROR CASES: 65*f6dc9357SAndroid Build Coastguard Worker If the function returns error code, then (*processedSize) is size of 66*f6dc9357SAndroid Build Coastguard Worker data written from (data) buffer. 67*f6dc9357SAndroid Build Coastguard Worker */ 68*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_ISequentialOutStream(x) \ 69*f6dc9357SAndroid Build Coastguard Worker x(Write(const void *data, UInt32 size, UInt32 *processedSize)) 70*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(ISequentialOutStream, 0x02) 71*f6dc9357SAndroid Build Coastguard Worker 72*f6dc9357SAndroid Build Coastguard Worker 73*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32 74*f6dc9357SAndroid Build Coastguard Worker 75*f6dc9357SAndroid Build Coastguard Worker #ifdef __HRESULT_FROM_WIN32 76*f6dc9357SAndroid Build Coastguard Worker #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) 77*f6dc9357SAndroid Build Coastguard Worker #else 78*f6dc9357SAndroid Build Coastguard Worker #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK) 79*f6dc9357SAndroid Build Coastguard Worker #endif 80*f6dc9357SAndroid Build Coastguard Worker 81*f6dc9357SAndroid Build Coastguard Worker #else 82*f6dc9357SAndroid Build Coastguard Worker 83*f6dc9357SAndroid Build Coastguard Worker #define HRESULT_WIN32_ERROR_NEGATIVE_SEEK MY_E_ERROR_NEGATIVE_SEEK 84*f6dc9357SAndroid Build Coastguard Worker 85*f6dc9357SAndroid Build Coastguard Worker #endif 86*f6dc9357SAndroid Build Coastguard Worker 87*f6dc9357SAndroid Build Coastguard Worker 88*f6dc9357SAndroid Build Coastguard Worker /* 89*f6dc9357SAndroid Build Coastguard Worker IInStream::Seek() / IOutStream::Seek() 90*f6dc9357SAndroid Build Coastguard Worker If you seek to position before the beginning of the stream, 91*f6dc9357SAndroid Build Coastguard Worker Seek() function returns error code: 92*f6dc9357SAndroid Build Coastguard Worker Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK). 93*f6dc9357SAndroid Build Coastguard Worker or STG_E_INVALIDFUNCTION 94*f6dc9357SAndroid Build Coastguard Worker It is allowed to seek past the end of the stream. 95*f6dc9357SAndroid Build Coastguard Worker if Seek() returns error, then the value of *newPosition is undefined. 96*f6dc9357SAndroid Build Coastguard Worker */ 97*f6dc9357SAndroid Build Coastguard Worker 98*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IInStream(x) \ 99*f6dc9357SAndroid Build Coastguard Worker x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) 100*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM_SUB(IInStream, ISequentialInStream, 0x03) 101*f6dc9357SAndroid Build Coastguard Worker 102*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IOutStream(x) \ 103*f6dc9357SAndroid Build Coastguard Worker x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) \ 104*f6dc9357SAndroid Build Coastguard Worker x(SetSize(UInt64 newSize)) 105*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM_SUB(IOutStream, ISequentialOutStream, 0x04) 106*f6dc9357SAndroid Build Coastguard Worker 107*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IStreamGetSize(x) \ 108*f6dc9357SAndroid Build Coastguard Worker x(GetSize(UInt64 *size)) 109*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IStreamGetSize, 0x06) 110*f6dc9357SAndroid Build Coastguard Worker 111*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IOutStreamFinish(x) \ 112*f6dc9357SAndroid Build Coastguard Worker x(OutStreamFinish()) 113*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IOutStreamFinish, 0x07) 114*f6dc9357SAndroid Build Coastguard Worker 115*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IStreamGetProps(x) \ 116*f6dc9357SAndroid Build Coastguard Worker x(GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)) 117*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IStreamGetProps, 0x08) 118*f6dc9357SAndroid Build Coastguard Worker 119*f6dc9357SAndroid Build Coastguard Worker 120*f6dc9357SAndroid Build Coastguard Worker struct CStreamFileProps 121*f6dc9357SAndroid Build Coastguard Worker { 122*f6dc9357SAndroid Build Coastguard Worker UInt64 Size; 123*f6dc9357SAndroid Build Coastguard Worker UInt64 VolID; 124*f6dc9357SAndroid Build Coastguard Worker UInt64 FileID_Low; 125*f6dc9357SAndroid Build Coastguard Worker UInt64 FileID_High; 126*f6dc9357SAndroid Build Coastguard Worker UInt32 NumLinks; 127*f6dc9357SAndroid Build Coastguard Worker UInt32 Attrib; 128*f6dc9357SAndroid Build Coastguard Worker FILETIME CTime; 129*f6dc9357SAndroid Build Coastguard Worker FILETIME ATime; 130*f6dc9357SAndroid Build Coastguard Worker FILETIME MTime; 131*f6dc9357SAndroid Build Coastguard Worker }; 132*f6dc9357SAndroid Build Coastguard Worker 133*f6dc9357SAndroid Build Coastguard Worker 134*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IStreamGetProps2(x) \ 135*f6dc9357SAndroid Build Coastguard Worker x(GetProps2(CStreamFileProps *props)) 136*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IStreamGetProps2, 0x09) 137*f6dc9357SAndroid Build Coastguard Worker 138*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IStreamGetProp(x) \ 139*f6dc9357SAndroid Build Coastguard Worker x(GetProperty(PROPID propID, PROPVARIANT *value)) \ 140*f6dc9357SAndroid Build Coastguard Worker x(ReloadProps()) 141*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IStreamGetProp, 0x0a) 142*f6dc9357SAndroid Build Coastguard Worker 143*f6dc9357SAndroid Build Coastguard Worker 144*f6dc9357SAndroid Build Coastguard Worker /* 145*f6dc9357SAndroid Build Coastguard Worker IStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end) 146*f6dc9357SAndroid Build Coastguard Worker 147*f6dc9357SAndroid Build Coastguard Worker It sets region of data in output stream that is restricted. 148*f6dc9357SAndroid Build Coastguard Worker For restricted region it's expected (or allowed) 149*f6dc9357SAndroid Build Coastguard Worker that the caller can write to same region with different calls of Write()/SetSize(). 150*f6dc9357SAndroid Build Coastguard Worker Another regions of output stream will be supposed as non-restricted: 151*f6dc9357SAndroid Build Coastguard Worker - The callee usually doesn't flush the data in restricted region. 152*f6dc9357SAndroid Build Coastguard Worker - The callee usually can flush data from non-restricted region after writing. 153*f6dc9357SAndroid Build Coastguard Worker 154*f6dc9357SAndroid Build Coastguard Worker Actual restiction rules depend also from current stream position. 155*f6dc9357SAndroid Build Coastguard Worker It's recommended to call SetRestriction() just before the Write() call. 156*f6dc9357SAndroid Build Coastguard Worker So the callee can optimize writing and flushing, if that Write() 157*f6dc9357SAndroid Build Coastguard Worker operation is not restricted. 158*f6dc9357SAndroid Build Coastguard Worker 159*f6dc9357SAndroid Build Coastguard Worker Note: Each new call of SetRestriction() sets new restictions, 160*f6dc9357SAndroid Build Coastguard Worker so previous restrction calls has no effect anymore. 161*f6dc9357SAndroid Build Coastguard Worker 162*f6dc9357SAndroid Build Coastguard Worker inputs: 163*f6dc9357SAndroid Build Coastguard Worker 164*f6dc9357SAndroid Build Coastguard Worker (begin > end) is not allowed, and returns E_FAIL; 165*f6dc9357SAndroid Build Coastguard Worker 166*f6dc9357SAndroid Build Coastguard Worker if (begin == end) 167*f6dc9357SAndroid Build Coastguard Worker { 168*f6dc9357SAndroid Build Coastguard Worker No restriction. 169*f6dc9357SAndroid Build Coastguard Worker The caller will call Write() in sequential order. 170*f6dc9357SAndroid Build Coastguard Worker After SetRestriction(begin, begin), but before next call of SetRestriction() 171*f6dc9357SAndroid Build Coastguard Worker { 172*f6dc9357SAndroid Build Coastguard Worker Additional condition: 173*f6dc9357SAndroid Build Coastguard Worker it's expected that current stream seek position is equal to stream size. 174*f6dc9357SAndroid Build Coastguard Worker The callee can make final flushing for any data before current stream seek position. 175*f6dc9357SAndroid Build Coastguard Worker For each Write(size) call: 176*f6dc9357SAndroid Build Coastguard Worker The callee can make final flushing for that new written data. 177*f6dc9357SAndroid Build Coastguard Worker } 178*f6dc9357SAndroid Build Coastguard Worker The pair of values (begin == 0 && end == 0) is recommended to remove write restriction. 179*f6dc9357SAndroid Build Coastguard Worker } 180*f6dc9357SAndroid Build Coastguard Worker 181*f6dc9357SAndroid Build Coastguard Worker if (begin < end) 182*f6dc9357SAndroid Build Coastguard Worker { 183*f6dc9357SAndroid Build Coastguard Worker it means that callee must NOT flush any data in region [begin, end). 184*f6dc9357SAndroid Build Coastguard Worker The caller is allowed to Seek() to that region and rewrite the 185*f6dc9357SAndroid Build Coastguard Worker data in that restriction region. 186*f6dc9357SAndroid Build Coastguard Worker if (end == (UInt64)(Int64)-1) 187*f6dc9357SAndroid Build Coastguard Worker { 188*f6dc9357SAndroid Build Coastguard Worker there is no upper bound for restricted region. 189*f6dc9357SAndroid Build Coastguard Worker So non-restricted region will be [0, begin) in that case 190*f6dc9357SAndroid Build Coastguard Worker } 191*f6dc9357SAndroid Build Coastguard Worker } 192*f6dc9357SAndroid Build Coastguard Worker 193*f6dc9357SAndroid Build Coastguard Worker returns: 194*f6dc9357SAndroid Build Coastguard Worker - if (begin > end) it return ERROR code (E_FAIL) 195*f6dc9357SAndroid Build Coastguard Worker - S_OK : if no errors. 196*f6dc9357SAndroid Build Coastguard Worker - Also the call of SetRestriction() can initiate the flushing of already written data. 197*f6dc9357SAndroid Build Coastguard Worker So it can return the result of that flushing. 198*f6dc9357SAndroid Build Coastguard Worker 199*f6dc9357SAndroid Build Coastguard Worker Note: IOutStream::SetSize() also can change the data. 200*f6dc9357SAndroid Build Coastguard Worker So it's not expected the call 201*f6dc9357SAndroid Build Coastguard Worker IOutStream::SetSize() to region that was written before as unrestricted. 202*f6dc9357SAndroid Build Coastguard Worker */ 203*f6dc9357SAndroid Build Coastguard Worker 204*f6dc9357SAndroid Build Coastguard Worker #define Z7_IFACEM_IStreamSetRestriction(x) \ 205*f6dc9357SAndroid Build Coastguard Worker x(SetRestriction(UInt64 begin, UInt64 end)) \ 206*f6dc9357SAndroid Build Coastguard Worker 207*f6dc9357SAndroid Build Coastguard Worker Z7_IFACE_CONSTR_STREAM(IStreamSetRestriction, 0x10) 208*f6dc9357SAndroid Build Coastguard Worker 209*f6dc9357SAndroid Build Coastguard Worker Z7_PURE_INTERFACES_END 210*f6dc9357SAndroid Build Coastguard Worker #endif 211