mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
11 KiB
491 lines
11 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 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 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;
|
|
|
|
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);
|
|
|
|
if (nCount == 0)
|
|
return 0;
|
|
|
|
ASSERT(AfxIsValidAddress(lpBuf, nCount));
|
|
|
|
// read from the stream
|
|
DWORD dwBytesRead;
|
|
SCODE sc = m_lpStream->Read(lpBuf, nCount, &dwBytesRead);
|
|
if (sc != S_OK)
|
|
_AfxThrowOleFileException(sc);
|
|
|
|
// always return number of bytes read (will always fit in UINT)
|
|
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);
|
|
ASSERT(m_lpStream != NULL);
|
|
|
|
if (m_lpStream != NULL)
|
|
{
|
|
// commit the stream via Flush (which can be overriden)
|
|
Flush();
|
|
RELEASE(m_lpStream);
|
|
}
|
|
|
|
m_strStorageName.Empty();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// 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)
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|