///////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/private/comstream.h
// Purpose: COM Stream adapter to wxStreamBase based streams
// Created: 2021-01-15
// Copyright: (c) 2021 wxWidgets team
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef WX_COMSTREAM_H
#define WX_COMSTREAM_H
#include "wx/stream.h"
#include "wx/msw/ole/comimpl.h"
class wxCOMBaseStreamAdapter : public IStream
{
public:
wxCOMBaseStreamAdapter(wxStreamBase* stream):
m_stream(stream)
{ }
virtual ~wxCOMBaseStreamAdapter() = default;
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override
{
if (riid == IID_IUnknown ||
riid == IID_ISequentialStream ||
riid == IID_IStream)
{
*ppv = this;
AddRef();
return S_OK;
}
*ppv = nullptr;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) AddRef() override
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) Release() override
{
if (--m_cRef == wxAutoULong(0))
{
delete this;
return 0;
}
else
return m_cRef;
}
// IStream
virtual HRESULT STDMETHODCALLTYPE Seek(
LARGE_INTEGER WXUNUSED(dlibMove), DWORD WXUNUSED(dwOrigin),
ULARGE_INTEGER *WXUNUSED(plibNewPosition)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER WXUNUSED(libNewSize)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *WXUNUSED(pstm),
ULARGE_INTEGER WXUNUSED(cb), ULARGE_INTEGER *WXUNUSED(pcbRead),
ULARGE_INTEGER *WXUNUSED(pcbWritten)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD WXUNUSED(grfCommitFlags)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Revert(void) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER WXUNUSED(libOffset),
ULARGE_INTEGER WXUNUSED(cb), DWORD WXUNUSED(dwLockType)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER WXUNUSED(libOffset),
ULARGE_INTEGER WXUNUSED(cb), DWORD WXUNUSED(dwLockType)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD WXUNUSED(grfStatFlag)) override
{
pstatstg->type = STGTY_STREAM;
pstatstg->cbSize.QuadPart = m_stream->GetSize();
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **WXUNUSED(ppstm)) override
{
return E_NOTIMPL;
}
// ISequentialStream
virtual HRESULT STDMETHODCALLTYPE Read(void *WXUNUSED(pv),
ULONG WXUNUSED(cb), ULONG *WXUNUSED(pcbRead)) override
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Write(const void *WXUNUSED(pv),
ULONG WXUNUSED(cb), ULONG *WXUNUSED(pcbWritten)) override
{
return E_NOTIMPL;
}
protected:
wxStreamBase* m_stream;
static wxSeekMode OriginToSeekMode(DWORD origin)
{
switch (origin)
{
case STREAM_SEEK_SET:
return wxFromStart;
case STREAM_SEEK_CUR:
return wxFromCurrent;
case STREAM_SEEK_END:
return wxFromEnd;
}
return wxFromStart;
}
private:
wxAutoULong m_cRef;
};
class wxCOMInputStreamAdapter : public wxCOMBaseStreamAdapter
{
public:
wxCOMInputStreamAdapter(wxInputStream* stream):
wxCOMBaseStreamAdapter(stream)
{
}
virtual HRESULT STDMETHODCALLTYPE Seek(
LARGE_INTEGER dlibMove, DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition) override
{
wxFileOffset newOffset = reinterpret_cast<wxInputStream*>(m_stream)->SeekI(dlibMove.QuadPart, OriginToSeekMode(dwOrigin));
if (plibNewPosition)
plibNewPosition->QuadPart = newOffset;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead) override
{
wxInputStream* inputStr = reinterpret_cast<wxInputStream*>(m_stream);
inputStr->Read(pv, cb);
*pcbRead = inputStr->LastRead();
return S_OK;
}
};
class wxCOMOutputStreamAdapter : public wxCOMBaseStreamAdapter
{
public:
wxCOMOutputStreamAdapter(wxOutputStream* stream) :
wxCOMBaseStreamAdapter(stream)
{ }
virtual HRESULT STDMETHODCALLTYPE Seek(
LARGE_INTEGER dlibMove, DWORD dwOrigin,
ULARGE_INTEGER *plibNewPosition) override
{
wxFileOffset newOffset = reinterpret_cast<wxOutputStream*>(m_stream)->SeekO(dlibMove.QuadPart, OriginToSeekMode(dwOrigin));
if (plibNewPosition)
plibNewPosition->QuadPart = newOffset;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten) override
{
wxOutputStream* outputStr = reinterpret_cast<wxOutputStream*>(m_stream);
outputStr->Write(pv, cb);
*pcbWritten = outputStr->LastWrite();
return S_OK;
}
};
#endif // WX_COMSTREAM_H