home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_OLE_SEG
- #pragma code_seg(AFX_OLE_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // COleStreamFile implementation
-
- COleStreamFile::COleStreamFile(LPSTREAM lpStream)
- {
- m_lpStream = lpStream;
-
- m_strStorageName.Empty();
- if (m_lpStream != NULL)
- {
- USES_CONVERSION;
- STATSTG statstg;
- if (m_lpStream->Stat(&statstg, 0) == S_OK)
- {
- if (statstg.pwcsName != NULL)
- {
- TCHAR szTemp[_MAX_PATH];
-
- AfxFullPath(szTemp, OLE2CT(statstg.pwcsName));
- CoTaskMemFree(statstg.pwcsName);
-
- m_strStorageName = szTemp;
- }
- }
- }
- }
-
- COleStreamFile::~COleStreamFile()
- {
- if (m_lpStream != NULL && m_bCloseOnDelete)
- {
- Close();
- ASSERT(m_lpStream == NULL);
- }
- }
-
- LPSTREAM COleStreamFile::Detach()
- {
- LPSTREAM lpStream = m_lpStream;
- m_lpStream = NULL; // detach and transfer ownership of m_lpStream
- return lpStream;
- }
-
- void COleStreamFile::Attach(LPSTREAM lpStream)
- {
- ASSERT(m_lpStream == NULL); // already attached to an LPSTREAM?
- ASSERT(lpStream != NULL);
-
- m_lpStream = lpStream;
- m_bCloseOnDelete = FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // OLE streams helper
-
- HRESULT AFXAPI _AfxReadFromStream(LPSTREAM pStream, void* lpBuf, UINT nCount, DWORD& nRead)
- {
- if (nCount == 0)
- {
- nRead = 0;
- return S_OK;
- }
-
- ASSERT(AfxIsValidAddress(lpBuf, nCount));
- ASSERT(pStream != NULL);
-
- // read from the stream
- SCODE sc = pStream->Read(lpBuf, nCount, &nRead);
- return ResultFromScode(sc);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // OLE CFileException helpers
-
- void AFXAPI _AfxFillOleFileException(CFileException* pError, SCODE sc)
- {
- ASSERT(pError != NULL);
- ASSERT(FAILED(sc));
-
- int cause; // portable CFileException.m_cause
-
- // error codes 255 or less are DOS/Win32 error codes
- if (SCODE_SEVERITY(sc) == SEVERITY_ERROR &&
- SCODE_FACILITY(sc) == FACILITY_STORAGE &&
- SCODE_CODE(sc) < 0x100)
- {
- ASSERT(SCODE_CODE(sc) != 0);
-
- // throw an exception matching to the DOS error
- // (NOTE: only the DOS error part of the SCODE becomes m_lOsError)
- cause = CFileException::OsErrorToException(SCODE_CODE(sc));
- sc = (SCODE)SCODE_CODE(sc);
- }
- else
- {
- // attempt some conversion of storage specific error codes to generic
- // CFileException causes...
- switch (sc)
- {
- case STG_E_INUSE:
- case STG_E_SHAREREQUIRED:
- cause = CFileException::sharingViolation;
- break;
-
- case STG_E_NOTCURRENT:
- case STG_E_REVERTED:
- case STG_E_CANTSAVE:
- case STG_E_OLDFORMAT:
- case STG_E_OLDDLL:
- cause = CFileException::generic;
- break;
-
- default:
- cause = CFileException::generic;
- break;
- }
- }
-
- // fill in pError
- pError->m_cause = cause;
- pError->m_lOsError = (LONG)sc;
- }
-
- void AFXAPI _AfxThrowOleFileException(SCODE sc)
- {
- // ignore non-failure codes
- if (!FAILED(sc))
- return;
-
- // otherwise, construct and exception and throw it
- CFileException e;
- _AfxFillOleFileException(&e, sc);
- AfxThrowFileException(e.m_cause, e.m_lOsError);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleStreamFile Attributes
-
- BOOL COleStreamFile::GetStatus(CFileStatus& rStatus) const
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- // get status of the stream
- STATSTG statstg;
- if (m_lpStream->Stat(&statstg, 0) != S_OK)
- return FALSE;
-
- // map to CFileStatus struct
- rStatus.m_mtime = CTime(statstg.mtime);
- rStatus.m_ctime = CTime(statstg.ctime);
- rStatus.m_atime = CTime(statstg.atime);
- ASSERT(statstg.cbSize.HighPart == 0);
- rStatus.m_size = statstg.cbSize.LowPart;
- rStatus.m_attribute = 0;
- rStatus.m_szFullName[0] = '\0';
- if (statstg.pwcsName != NULL)
- {
- // name was returned -- copy and free it
- lstrcpyn(rStatus.m_szFullName, OLE2CT(statstg.pwcsName),
- _countof(rStatus.m_szFullName));
- CoTaskMemFree(statstg.pwcsName);
- }
- return TRUE;
- }
-
- const CString COleStreamFile::GetStorageName() const
- {
- ASSERT_VALID(this);
- return m_strStorageName;
- }
-
-
- DWORD COleStreamFile::GetPosition() const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- ULARGE_INTEGER liPosition;
- LARGE_INTEGER liZero; LISet32(liZero, 0);
- SCODE sc = m_lpStream->Seek(liZero, STREAM_SEEK_CUR, &liPosition);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
-
- ASSERT(liPosition.HighPart == 0);
- return liPosition.LowPart;
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // COleStreamFile Operations
-
- BOOL COleStreamFile::OpenStream(LPSTORAGE lpStorage, LPCTSTR lpszStreamName,
- DWORD nOpenFlags, CFileException* pError)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpStream == NULL);
- ASSERT(lpStorage != NULL);
- ASSERT(AfxIsValidString(lpszStreamName));
- ASSERT(pError == NULL ||
- AfxIsValidAddress(pError, sizeof(CFileException)));
-
- SCODE sc = lpStorage->OpenStream(T2COLE(lpszStreamName), NULL, nOpenFlags, 0,
- &m_lpStream);
- if (FAILED(sc) && pError != NULL)
- _AfxFillOleFileException(pError, sc);
-
- ASSERT(FAILED(sc) || m_lpStream != NULL);
- return !FAILED(sc);
- }
-
- BOOL COleStreamFile::CreateStream(LPSTORAGE lpStorage, LPCTSTR lpszStreamName,
- DWORD nOpenFlags, CFileException* pError)
- {
- USES_CONVERSION;
-
- ASSERT_VALID(this);
- ASSERT(m_lpStream == NULL);
- ASSERT(lpStorage != NULL);
- ASSERT(AfxIsValidString(lpszStreamName));
- ASSERT(pError == NULL ||
- AfxIsValidAddress(pError, sizeof(CFileException)));
-
- STATSTG statstg;
- if (lpStorage->Stat(&statstg, 0) == S_OK)
- {
- if (statstg.pwcsName != NULL)
- {
- TCHAR szTemp[_MAX_PATH];
-
- AfxFullPath(szTemp, OLE2CT(statstg.pwcsName));
- CoTaskMemFree(statstg.pwcsName);
-
- m_strStorageName = szTemp;
- }
- }
-
- SCODE sc = lpStorage->CreateStream(T2COLE(lpszStreamName), nOpenFlags,
- 0, 0, &m_lpStream);
-
- if (FAILED(sc) && pError != NULL)
- _AfxFillOleFileException(pError, sc);
-
- ASSERT(FAILED(sc) || m_lpStream != NULL);
- return !FAILED(sc);
- }
-
- BOOL COleStreamFile::CreateMemoryStream(CFileException* pError)
- {
- ASSERT_VALID(this);
- ASSERT(pError == NULL ||
- AfxIsValidAddress(pError, sizeof(CFileException)));
-
- SCODE sc = CreateStreamOnHGlobal(NULL, TRUE, &m_lpStream);
- if (FAILED(sc) && pError != NULL)
- _AfxFillOleFileException(pError, sc);
-
- ASSERT(FAILED(sc) || m_lpStream != NULL);
- return !FAILED(sc);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleStreamFile Overrides
-
- CFile* COleStreamFile::Duplicate() const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- LPSTREAM lpStream;
- SCODE sc = m_lpStream->Clone(&lpStream);
- if (FAILED(sc))
- _AfxThrowOleFileException(sc);
-
- ASSERT(lpStream != NULL);
- COleStreamFile* pFile = NULL;
-
- TRY
- {
- // attempt to create the stream
- pFile = new COleStreamFile(lpStream);
- pFile->m_bCloseOnDelete = m_bCloseOnDelete;
- }
- CATCH_ALL(e)
- {
- // cleanup cloned stream
- lpStream->Release();
- THROW_LAST();
- }
- END_CATCH_ALL
-
- ASSERT(pFile != NULL);
- return pFile;
- }
-
- LONG COleStreamFile::Seek(LONG lOff, UINT nFrom)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- ASSERT(STREAM_SEEK_SET == begin);
- ASSERT(STREAM_SEEK_CUR == current);
- ASSERT(STREAM_SEEK_END == end);
-
- ULARGE_INTEGER liNewPosition;
- LARGE_INTEGER liOff;
- LISet32(liOff, lOff);
- SCODE sc = m_lpStream->Seek(liOff, nFrom, &liNewPosition);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
-
- ASSERT(liNewPosition.HighPart == 0);
- return liNewPosition.LowPart;
- }
-
- void COleStreamFile::SetLength(DWORD dwNewLen)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- ULARGE_INTEGER liNewLen;
- ULISet32(liNewLen, dwNewLen);
- SCODE sc = m_lpStream->SetSize(liNewLen);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
- }
-
- DWORD COleStreamFile::GetLength() const
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- // get status of the stream
- STATSTG statstg;
- SCODE sc = m_lpStream->Stat(&statstg, STATFLAG_NONAME);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
-
- // map to CFileStatus struct
- ASSERT(statstg.cbSize.HighPart == 0);
- return statstg.cbSize.LowPart;
- }
-
- UINT COleStreamFile::Read(void* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- DWORD dwBytesRead;
- HRESULT hr = _AfxReadFromStream(m_lpStream, lpBuf, nCount, dwBytesRead);
-
- if (hr != S_OK)
- _AfxThrowOleFileException(hr);
-
- // always return number of bytes read
- return (UINT)dwBytesRead;
- }
-
- void COleStreamFile::Write(const void* lpBuf, UINT nCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- if (nCount == 0)
- return;
-
- ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
-
- // write to the stream
- DWORD dwBytesWritten;
- SCODE sc = m_lpStream->Write(lpBuf, nCount, &dwBytesWritten);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
-
- // if no error, all bytes should have been written
- ASSERT((UINT)dwBytesWritten == nCount);
- }
-
- void COleStreamFile::LockRange(DWORD dwPos, DWORD dwCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- // convert parameters to long integers
- ULARGE_INTEGER liPos;
- ULISet32(liPos, dwPos);
- ULARGE_INTEGER liCount;
- ULISet32(liCount, dwCount);
-
- // then lock the region
- SCODE sc = m_lpStream->LockRegion(liPos, liCount, LOCK_EXCLUSIVE);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
- }
-
- void COleStreamFile::UnlockRange(DWORD dwPos, DWORD dwCount)
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- // convert parameters to long integers
- ULARGE_INTEGER liPos;
- ULISet32(liPos, dwPos);
- ULARGE_INTEGER liCount;
- ULISet32(liCount, dwCount);
-
- // then lock the region
- SCODE sc = m_lpStream->UnlockRegion(liPos, liCount, LOCK_EXCLUSIVE);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
- }
-
- void COleStreamFile::Abort()
- {
- ASSERT_VALID(this);
-
- if (m_lpStream != NULL)
- {
- m_lpStream->Revert();
- RELEASE(m_lpStream);
- }
-
- m_strStorageName.Empty();
- }
-
- void COleStreamFile::Flush()
- {
- ASSERT_VALID(this);
- ASSERT(m_lpStream != NULL);
-
- // commit will return an error only if the stream is transacted
- SCODE sc = m_lpStream->Commit(0);
- if (sc != S_OK)
- _AfxThrowOleFileException(sc);
- }
-
- void COleStreamFile::Close()
- {
- ASSERT_VALID(this);
-
- if (m_lpStream != NULL)
- {
- // commit the stream via Flush (which can be overriden)
- Flush();
- RELEASE(m_lpStream);
- }
-
- m_strStorageName.Empty();
- }
-
- IStream* COleStreamFile::GetStream() const
- {
- return m_lpStream;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // COleStreamFile diagnostics
-
- #ifdef _DEBUG
- void COleStreamFile::AssertValid() const
- {
- CFile::AssertValid();
- }
-
- void COleStreamFile::Dump(CDumpContext& dc) const
- {
- CFile::Dump(dc);
-
- dc << "m_lpStream = " << m_lpStream;
- dc << "m_strStorageName = \"" << m_strStorageName;
- dc << "\"\n";
- }
- #endif
-
- ////////////////////////////////////////////////////////////////////////////
-
- #ifdef AFX_INIT_SEG
- #pragma code_seg(AFX_INIT_SEG)
- #endif
-
- IMPLEMENT_DYNAMIC(COleStreamFile, CFile)
-
- ////////////////////////////////////////////////////////////////////////////
-