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