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