123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- #include <kopano/platform.h>
- #include <new>
- #include <mapix.h>
- #include <kopano/ECGuid.h>
- #include <kopano/ECInterfaceDefs.h>
- #include <kopano/memory.hpp>
- #include "ECMemStream.h"
- #include <kopano/Trace.h>
- #include <kopano/ECDebug.h>
- #define EC_MEMBLOCK_SIZE 8192
- namespace KC {
- ECMemBlock::ECMemBlock(const char *buffer, ULONG ulDataLen, ULONG ulFlags) :
- ECUnknown("ECMemBlock")
- {
- this->ulFlags = ulFlags;
- if (ulDataLen == 0)
- return;
- cbTotal = ulDataLen;
- cbCurrent = ulDataLen;
- lpCurrent = (char *)malloc(ulDataLen);
- if (lpCurrent == nullptr)
- throw std::bad_alloc();
- memcpy(lpCurrent, buffer, ulDataLen);
- if (!(ulFlags & STGM_TRANSACTED))
- return;
- cbOriginal = ulDataLen;
- lpOriginal = (char *)malloc(ulDataLen);
- if (lpOriginal == nullptr)
- throw std::bad_alloc();
- memcpy(lpOriginal, buffer, ulDataLen);
- }
- ECMemBlock::~ECMemBlock()
- {
- free(lpCurrent);
- if (ulFlags & STGM_TRANSACTED)
- free(lpOriginal);
- }
- HRESULT ECMemBlock::Create(const char *buffer, ULONG ulDataLen, ULONG ulFlags,
- ECMemBlock **lppStream)
- {
- return alloc_wrap<ECMemBlock>(buffer, ulDataLen, ulFlags)
- .as(IID_ECMemBlock, lppStream);
- }
- HRESULT ECMemBlock::QueryInterface(REFIID refiid, void **lppInterface)
- {
- REGISTER_INTERFACE2(ECMemBlock, this);
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- HRESULT ECMemBlock::ReadAt(ULONG ulPos, ULONG ulLen, char *buffer, ULONG *ulBytesRead)
- {
- HRESULT hr = hrSuccess;
- ULONG ulToRead = cbCurrent - ulPos;
- ulToRead = ulLen < ulToRead ? ulLen : ulToRead;
- memcpy(buffer, lpCurrent+ulPos, ulToRead);
- if(ulBytesRead)
- *ulBytesRead = ulToRead;
- return hr;
- }
- HRESULT ECMemBlock::WriteAt(ULONG ulPos, ULONG ulLen, const char *buffer,
- ULONG *ulBytesWritten)
- {
- ULONG dsize = ulPos + ulLen;
-
- if(cbTotal < dsize) {
- ULONG newsize = cbTotal + ((dsize/EC_MEMBLOCK_SIZE)+1)*EC_MEMBLOCK_SIZE;
- auto lpNew = static_cast<char *>(realloc(lpCurrent, newsize));
- if (lpNew == NULL)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- lpCurrent = lpNew;
- memset(lpCurrent+cbTotal, 0, newsize-cbTotal);
- cbTotal = newsize;
- }
- if (dsize > cbCurrent)
- cbCurrent = ulPos + ulLen;
- memcpy(lpCurrent+ulPos, buffer, ulLen);
- if(ulBytesWritten)
- *ulBytesWritten = ulLen;
- return hrSuccess;
- }
- HRESULT ECMemBlock::Commit()
- {
- if (!(ulFlags & STGM_TRANSACTED))
- return hrSuccess;
- free(lpOriginal);
- lpOriginal = NULL;
- lpOriginal = (char *)malloc(cbCurrent);
- if (lpOriginal == NULL)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- cbOriginal = cbCurrent;
- memcpy(lpOriginal, lpCurrent, cbCurrent);
- return hrSuccess;
- }
- HRESULT ECMemBlock::Revert()
- {
- if (!(ulFlags & STGM_TRANSACTED))
- return hrSuccess;
- free(lpCurrent);
- lpCurrent = NULL;
- lpCurrent = (char *)malloc(cbOriginal);
- if (lpCurrent == NULL)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- cbCurrent = cbTotal = cbOriginal;
- memcpy(lpCurrent, lpOriginal, cbOriginal);
- return hrSuccess;
- }
- HRESULT ECMemBlock::SetSize(ULONG ulSize)
- {
- auto lpNew = static_cast<char *>(realloc(lpCurrent, ulSize));
- if (lpNew == NULL && ulSize != 0)
- return MAPI_E_NOT_ENOUGH_MEMORY;
- if(ulSize > cbCurrent)
- memset(lpNew+cbCurrent, 0, ulSize-cbCurrent);
- lpCurrent = lpNew;
- cbCurrent = ulSize;
- cbTotal = ulSize;
- return hrSuccess;
- }
- HRESULT ECMemBlock::GetSize(ULONG *ulSize) const
- {
- *ulSize = cbCurrent;
- return hrSuccess;
- }
- ECMemStream::ECMemStream(char *buffer, ULONG ulDataLen, ULONG ulFlags, CommitFunc lpCommitFunc, DeleteFunc lpDeleteFunc,
- void *lpParam) : ECUnknown("IStream")
- {
- this->liPos.QuadPart = 0;
- ECMemBlock::Create(buffer, ulDataLen, ulFlags, &this->lpMemBlock);
- this->lpCommitFunc = lpCommitFunc;
- this->lpDeleteFunc = lpDeleteFunc;
- this->lpParam = lpParam;
- this->ulFlags = ulFlags;
- }
- ECMemStream::ECMemStream(ECMemBlock *lpMemBlock, ULONG ulFlags, CommitFunc lpCommitFunc, DeleteFunc lpDeleteFunc,
- void *lpParam) : ECUnknown("IStream")
- {
- this->liPos.QuadPart = 0;
- this->lpMemBlock = lpMemBlock;
- lpMemBlock->AddRef();
- this->lpCommitFunc = lpCommitFunc;
- this->lpDeleteFunc = lpDeleteFunc;
- this->lpParam = lpParam;
- this->ulFlags = ulFlags;
- }
- ECMemStream::~ECMemStream()
- {
- ULONG refs = 0;
- if(this->lpMemBlock)
- refs = this->lpMemBlock->Release();
- if (refs == 0 && this->lpDeleteFunc)
- lpDeleteFunc(lpParam);
- }
- HRESULT ECMemStream::QueryInterface(REFIID refiid, void **lppInterface)
- {
- REGISTER_INTERFACE2(IStream, &this->m_xStream);
- REGISTER_INTERFACE2(ISequentialStream, &this->m_xStream);
- REGISTER_INTERFACE2(IUnknown, &this->m_xStream);
- REGISTER_INTERFACE2(ECMemStream, this);
- REGISTER_INTERFACE2(ECUnknown, this);
- return MAPI_E_INTERFACE_NOT_SUPPORTED;
- }
- ULONG ECMemStream::Release()
- {
-
-
-
-
- if (this->m_cRef == 1 && this->ulFlags & STGM_SHARE_EXCLUSIVE &&
- this->fDirty)
- this->Commit(0);
- return ECUnknown::Release();
- }
- HRESULT ECMemStream::Create(char *buffer, ULONG ulDataLen, ULONG ulFlags, CommitFunc lpCommitFunc, DeleteFunc lpDeleteFunc,
- void *lpParam, ECMemStream **lppStream)
- {
- return alloc_wrap<ECMemStream>(buffer, ulDataLen, ulFlags,
- lpCommitFunc, lpDeleteFunc, lpParam)
- .as(IID_ECMemStream, lppStream);
- }
- HRESULT ECMemStream::Create(ECMemBlock *lpMemBlock, ULONG ulFlags, CommitFunc lpCommitFunc, DeleteFunc lpDeleteFunc,
- void *lpParam, ECMemStream **lppStream)
- {
- return alloc_wrap<ECMemStream>(lpMemBlock, ulFlags, lpCommitFunc,
- lpDeleteFunc, lpParam).as(IID_ECMemStream, lppStream);
- }
- HRESULT ECMemStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
- {
- HRESULT hr = hrSuccess;
- ULONG ulRead = 0;
-
-
-
-
-
- hr = this->lpMemBlock->ReadAt((ULONG)this->liPos.QuadPart, cb, (char *)pv, &ulRead);
- liPos.QuadPart += ulRead;
- if(pcbRead)
- *pcbRead = ulRead;
- return hr;
- }
- HRESULT ECMemStream::Write(const void *pv, ULONG cb, ULONG *pcbWritten)
- {
- HRESULT hr;
- ULONG ulWritten = 0;
- if(!(ulFlags&STGM_WRITE))
- return MAPI_E_NO_ACCESS;
- hr = this->lpMemBlock->WriteAt((ULONG)this->liPos.QuadPart, cb, (char *)pv, &ulWritten);
- if(hr != hrSuccess)
- return hr;
- liPos.QuadPart += ulWritten;
- if(pcbWritten)
- *pcbWritten = ulWritten;
- fDirty = TRUE;
-
-
-
- if(!(ulFlags & STGM_TRANSACTED) && !(ulFlags & STGM_SHARE_EXCLUSIVE))
- Commit(0);
- return hrSuccess;
- }
- HRESULT ECMemStream::Seek(LARGE_INTEGER dlibmove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
- {
- HRESULT hr;
- ULONG ulSize = 0;
- hr = this->lpMemBlock->GetSize(&ulSize);
- if(hr != hrSuccess)
- return hr;
- switch(dwOrigin) {
- case SEEK_SET:
- liPos.QuadPart = dlibmove.QuadPart;
- break;
- case SEEK_CUR:
- liPos.QuadPart += dlibmove.QuadPart;
- break;
- case SEEK_END:
- liPos.QuadPart = ulSize + dlibmove.QuadPart;
- break;
- }
- if(liPos.QuadPart > ulSize)
- liPos.QuadPart = ulSize;
- if(plibNewPosition)
- plibNewPosition->QuadPart = liPos.QuadPart;
- return hrSuccess;
- }
- HRESULT ECMemStream::SetSize(ULARGE_INTEGER libNewSize)
- {
- HRESULT hr;
- if(!(ulFlags&STGM_WRITE))
- return MAPI_E_NO_ACCESS;
- hr = lpMemBlock->SetSize((ULONG)libNewSize.QuadPart);
- this->fDirty = TRUE;
- return hr;
- }
- HRESULT ECMemStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
- {
- HRESULT hr;
- ULONG ulOffset = 0;
- ULONG ulWritten = 0;
- ULONG ulSize = 0;
-
- hr = lpMemBlock->GetSize(&ulSize);
- if(hr != hrSuccess)
- return hr;
- assert(liPos.u.HighPart == 0);
- ulOffset = liPos.u.LowPart;
- while(cb.QuadPart && ulSize > ulOffset) {
- pstm->Write(this->lpMemBlock->GetBuffer() + ulOffset, std::min(ulSize - ulOffset, cb.u.LowPart), &ulWritten);
- ulOffset += ulWritten;
- cb.QuadPart -= ulWritten;
- }
- if(pcbRead)
- pcbRead->QuadPart = ulOffset - liPos.u.LowPart;
- if(pcbWritten)
- pcbWritten->QuadPart = ulOffset - liPos.u.LowPart;
- liPos.QuadPart = ulOffset;
- return hrSuccess;
- }
- HRESULT ECMemStream::Commit(DWORD grfCommitFlags)
- {
- HRESULT hr = hrSuccess;
- KCHL::object_ptr<IStream> lpClonedStream;
- hr = this->lpMemBlock->Commit();
- if(hr != hrSuccess)
- return hr;
-
- if(this->lpCommitFunc) {
- hr = this->Clone(&~lpClonedStream);
- if(hr != hrSuccess)
- return hr;
- hr = this->lpCommitFunc(lpClonedStream, lpParam);
- }
- this->fDirty = FALSE;
- return hr;
- }
- HRESULT ECMemStream::Revert()
- {
- HRESULT hr = hrSuccess;
- hr = this->lpMemBlock->Revert();
- this->liPos.QuadPart = 0;
- return hr;
- }
- HRESULT ECMemStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
- {
-
- return hrSuccess;
- }
- HRESULT ECMemStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
- {
- return hrSuccess;
-
- }
- HRESULT ECMemStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
- {
- HRESULT hr;
- ULONG ulSize = 0;
- if (pstatstg == NULL)
- return MAPI_E_INVALID_PARAMETER;
- hr = this->lpMemBlock->GetSize(&ulSize);
- if(hr != hrSuccess)
- return hr;
- memset(pstatstg, 0, sizeof(STATSTG));
- pstatstg->cbSize.QuadPart = ulSize;
- pstatstg->type = STGTY_STREAM;
- pstatstg->grfMode = ulFlags;
- return hrSuccess;
- }
- HRESULT ECMemStream::Clone(IStream **ppstm)
- {
- HRESULT hr = hrSuccess;
- ECMemStream *lpStream = NULL;
- ECMemStream::Create(this->lpMemBlock, ulFlags, this->lpCommitFunc, this->lpDeleteFunc, lpParam, &lpStream);
- hr = lpStream->QueryInterface(IID_IStream, (void **)ppstm);
- lpStream->Release();
- return hr;
- }
- ULONG ECMemStream::GetSize()
- {
- ULONG ulSize = 0;
- this->lpMemBlock->GetSize(&ulSize);
- return ulSize;
- }
- char* ECMemStream::GetBuffer()
- {
- return this->lpMemBlock->GetBuffer();
- }
- DEF_ULONGMETHOD1(TRACE_MAPI, ECMemStream, Stream, AddRef, (void))
- DEF_ULONGMETHOD1(TRACE_MAPI, ECMemStream, Stream, Release, (void))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, QueryInterface, (REFIID, refiid), (LPVOID *, lppInterface))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Read, (void *, pv), (ULONG, cb), (ULONG *, pcbRead))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Write, (const void *, pv), (ULONG, cb), (ULONG *, pcbWritten))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Seek, (LARGE_INTEGER, dlibmove), (DWORD, dwOrigin), (ULARGE_INTEGER *, plibNewPosition))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, SetSize, (ULARGE_INTEGER, libNewSize))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, CopyTo, (IStream *, pstm), (ULARGE_INTEGER, cb), (ULARGE_INTEGER *, pcbRead), (ULARGE_INTEGER *, pcbWritten))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Commit, (DWORD, grfCommitFlags))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Revert, (void))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, LockRegion, (ULARGE_INTEGER, libOffset), (ULARGE_INTEGER, cb), (DWORD, dwLockType))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, UnlockRegion, (ULARGE_INTEGER, libOffset), (ULARGE_INTEGER, cb), (DWORD, dwLockType))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Stat, (STATSTG *, pstatstg), (DWORD, grfStatFlag))
- DEF_HRMETHOD1(TRACE_MAPI, ECMemStream, Stream, Clone, (IStream **, ppstm))
- }
|