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