1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
#pragma once
#include "Stream.h"
namespace util {
// A wrapper around util::Stream to support the com object IStream.
// It assumes that the Stream will exist the entire lifetime of the StreamWrapper object.
class StreamWrapper : public IStream {
StreamWrapper(Stream &src) : src(src) {
refcount = 1;
}
~StreamWrapper() {}
public:
static StreamWrapper *create(Stream &src) {
return new StreamWrapper(src);
}
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObject)
{
if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || iid == __uuidof(ISequentialStream)) {
*ppvObject = static_cast<IStream*>(this);
AddRef();
return S_OK;
} else {
return E_NOINTERFACE;
}
}
virtual ULONG STDMETHODCALLTYPE AddRef(void) {
return (ULONG)InterlockedIncrement(&refcount);
}
virtual ULONG STDMETHODCALLTYPE Release(void) {
ULONG res = (ULONG) InterlockedDecrement(&refcount);
if (res == 0) delete this;
return res;
}
// ISequentialStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead) {
*pcbRead = ULONG(src.read(nat(cb), pv));
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG* pcbWritten) {
src.write(cb, pv);
*pcbWritten = cb;
return S_OK;
}
// IStream Interface
public:
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Revert(void) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Clone(IStream **) {
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, ULARGE_INTEGER* lpNewFilePointer) {
switch(dwOrigin) {
case STREAM_SEEK_SET:
src.seek(nat(liDistanceToMove.QuadPart));
break;
case STREAM_SEEK_CUR:
src.seek(nat(liDistanceToMove.QuadPart + src.pos()));
break;
case STREAM_SEEK_END:
src.seek(nat(liDistanceToMove.QuadPart - src.length()));
break;
default:
return STG_E_INVALIDFUNCTION;
break;
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag) {
pStatstg->cbSize.QuadPart = src.length();
return S_OK;
}
private:
LONG refcount;
Stream &src;
};
}
|