1 // StreamBinder.cpp 2 3 #include "StdAfx.h" 4 5 #include "../../Common/MyCom.h" 6 7 #include "StreamBinder.h" 8 9 class CBinderInStream: 10 public ISequentialInStream, 11 public CMyUnknownImp 12 { 13 CStreamBinder *_binder; 14 public: 15 MY_UNKNOWN_IMP1(ISequentialInStream) 16 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 17 ~CBinderInStream() { _binder->CloseRead(); } 18 CBinderInStream(CStreamBinder *binder): _binder(binder) {} 19 }; 20 21 STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) 22 { return _binder->Read(data, size, processedSize); } 23 24 class CBinderOutStream: 25 public ISequentialOutStream, 26 public CMyUnknownImp 27 { 28 CStreamBinder *_binder; 29 public: 30 MY_UNKNOWN_IMP1(ISequentialOutStream) 31 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); 32 ~CBinderOutStream() { _binder->CloseWrite(); } 33 CBinderOutStream(CStreamBinder *binder): _binder(binder) {} 34 }; 35 36 STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) 37 { return _binder->Write(data, size, processedSize); } 38 39 40 41 WRes CStreamBinder::CreateEvents() 42 { 43 RINOK(_canWrite_Event.Create()); 44 RINOK(_canRead_Event.Create()); 45 return _readingWasClosed_Event.Create(); 46 } 47 48 void CStreamBinder::ReInit() 49 { 50 _canWrite_Event.Reset(); 51 _canRead_Event.Reset(); 52 _readingWasClosed_Event.Reset(); 53 54 // _readingWasClosed = false; 55 _readingWasClosed2 = false; 56 57 _waitWrite = true; 58 _bufSize = 0; 59 _buf = NULL; 60 ProcessedSize = 0; 61 // WritingWasCut = false; 62 } 63 64 65 void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream) 66 { 67 // _readingWasClosed = false; 68 _readingWasClosed2 = false; 69 70 _waitWrite = true; 71 _bufSize = 0; 72 _buf = NULL; 73 ProcessedSize = 0; 74 // WritingWasCut = false; 75 76 CBinderInStream *inStreamSpec = new CBinderInStream(this); 77 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); 78 *inStream = inStreamLoc.Detach(); 79 80 CBinderOutStream *outStreamSpec = new CBinderOutStream(this); 81 CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); 82 *outStream = outStreamLoc.Detach(); 83 } 84 85 // (_canRead_Event && _bufSize == 0) means that stream is finished. 86 87 HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) 88 { 89 if (processedSize) 90 *processedSize = 0; 91 if (size != 0) 92 { 93 if (_waitWrite) 94 { 95 RINOK(_canRead_Event.Lock()); 96 _waitWrite = false; 97 } 98 if (size > _bufSize) 99 size = _bufSize; 100 if (size != 0) 101 { 102 memcpy(data, _buf, size); 103 _buf = ((const Byte *)_buf) + size; 104 ProcessedSize += size; 105 if (processedSize) 106 *processedSize = size; 107 _bufSize -= size; 108 if (_bufSize == 0) 109 { 110 _waitWrite = true; 111 _canRead_Event.Reset(); 112 _canWrite_Event.Set(); 113 } 114 } 115 } 116 return S_OK; 117 } 118 119 HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) 120 { 121 if (processedSize) 122 *processedSize = 0; 123 if (size == 0) 124 return S_OK; 125 126 if (!_readingWasClosed2) 127 { 128 _buf = data; 129 _bufSize = size; 130 _canRead_Event.Set(); 131 132 /* 133 _canWrite_Event.Lock(); 134 if (_readingWasClosed) 135 _readingWasClosed2 = true; 136 */ 137 138 HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event }; 139 DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); 140 if (waitResult >= WAIT_OBJECT_0 + 2) 141 return E_FAIL; 142 143 size -= _bufSize; 144 if (size != 0) 145 { 146 if (processedSize) 147 *processedSize = size; 148 return S_OK; 149 } 150 // if (waitResult == WAIT_OBJECT_0 + 1) 151 _readingWasClosed2 = true; 152 } 153 154 // WritingWasCut = true; 155 return k_My_HRESULT_WritingWasCut; 156 } 157