Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

373 lines
7.6 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_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
////////////////////////////////////////////////////////////////////////////
// CMemFile implementation
CMemFile::CMemFile(UINT nGrowBytes)
{
ASSERT(nGrowBytes <= UINT_MAX);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
m_lpBuffer = NULL;
m_bAutoDelete = TRUE;
}
CMemFile::CMemFile(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
{
ASSERT(nGrowBytes <= UINT_MAX);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = nBufferSize;
m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
m_lpBuffer = lpBuffer;
m_bAutoDelete = FALSE;
}
void CMemFile::Attach(BYTE* lpBuffer, UINT nBufferSize, UINT nGrowBytes)
{
ASSERT(m_lpBuffer == NULL);
m_nGrowBytes = nGrowBytes;
m_nPosition = 0;
m_nBufferSize = nBufferSize;
m_nFileSize = nGrowBytes == 0 ? nBufferSize : 0;
m_lpBuffer = lpBuffer;
m_bAutoDelete = FALSE;
}
BYTE* CMemFile::Detach()
{
BYTE* lpBuffer = m_lpBuffer;
m_lpBuffer = NULL;
m_nFileSize = 0;
m_nBufferSize = 0;
m_nPosition = 0;
return lpBuffer;
}
CMemFile::~CMemFile()
{
// Close should have already been called, but we check anyway
if (m_lpBuffer)
Close();
ASSERT(m_lpBuffer == NULL);
m_nGrowBytes = 0;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
}
BYTE* CMemFile::Alloc(DWORD nBytes)
{
return (BYTE*)malloc((UINT)nBytes);
}
BYTE* CMemFile::Realloc(BYTE* lpMem, DWORD nBytes)
{
return (BYTE*)realloc(lpMem, (UINT)nBytes);
}
#pragma intrinsic(memcpy)
BYTE* CMemFile::Memcpy(BYTE* lpMemTarget, const BYTE* lpMemSource,
UINT nBytes)
{
ASSERT(lpMemTarget != NULL);
ASSERT(lpMemSource != NULL);
ASSERT(AfxIsValidAddress(lpMemTarget, nBytes));
ASSERT(AfxIsValidAddress(lpMemSource, nBytes, FALSE));
return (BYTE*)memcpy(lpMemTarget, lpMemSource, nBytes);
}
#pragma function(memcpy)
void CMemFile::Free(BYTE* lpMem)
{
ASSERT(lpMem != NULL);
free(lpMem);
}
DWORD CMemFile::GetPosition() const
{
ASSERT_VALID(this);
return m_nPosition;
}
void CMemFile::GrowFile(DWORD dwNewLen)
{
ASSERT_VALID(this);
if (dwNewLen > m_nBufferSize)
{
// grow the buffer
DWORD dwNewBufferSize = (DWORD)m_nBufferSize;
// watch out for buffers which cannot be grown!
ASSERT(m_nGrowBytes != 0);
if (m_nGrowBytes == 0)
AfxThrowMemoryException();
// determine new buffer size
while (dwNewBufferSize < dwNewLen)
dwNewBufferSize += m_nGrowBytes;
// allocate new buffer
BYTE* lpNew;
if (m_lpBuffer == NULL)
lpNew = Alloc(dwNewBufferSize);
else
lpNew = Realloc(m_lpBuffer, dwNewBufferSize);
if (lpNew == NULL)
AfxThrowMemoryException();
m_lpBuffer = lpNew;
m_nBufferSize = dwNewBufferSize;
}
ASSERT_VALID(this);
}
void CMemFile::SetLength(DWORD dwNewLen)
{
ASSERT_VALID(this);
if (dwNewLen > m_nBufferSize)
GrowFile(dwNewLen);
if (dwNewLen < m_nPosition)
m_nPosition = dwNewLen;
m_nFileSize = dwNewLen;
ASSERT_VALID(this);
}
UINT CMemFile::Read(void* lpBuf, UINT nCount)
{
ASSERT_VALID(this);
if (nCount == 0)
return 0;
ASSERT(lpBuf != NULL);
ASSERT(AfxIsValidAddress(lpBuf, nCount));
if (m_nPosition > m_nFileSize)
return 0;
UINT nRead;
if (m_nPosition + nCount > m_nFileSize)
nRead = (UINT)(m_nFileSize - m_nPosition);
else
nRead = nCount;
Memcpy((BYTE*)lpBuf, (BYTE*)m_lpBuffer + m_nPosition, nRead);
m_nPosition += nRead;
ASSERT_VALID(this);
return nRead;
}
void CMemFile::Write(const void* lpBuf, UINT nCount)
{
ASSERT_VALID(this);
if (nCount == 0)
return;
ASSERT(lpBuf != NULL);
ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
if (m_nPosition + nCount > m_nBufferSize)
GrowFile(m_nPosition + nCount);
ASSERT(m_nPosition + nCount <= m_nBufferSize);
Memcpy((BYTE*)m_lpBuffer + m_nPosition, (BYTE*)lpBuf, nCount);
m_nPosition += nCount;
if (m_nPosition > m_nFileSize)
m_nFileSize = m_nPosition;
ASSERT_VALID(this);
}
LONG CMemFile::Seek(LONG lOff, UINT nFrom)
{
ASSERT_VALID(this);
ASSERT(nFrom == begin || nFrom == end || nFrom == current);
LONG lNewPos = m_nPosition;
if (nFrom == begin)
lNewPos = lOff;
else if (nFrom == current)
lNewPos += lOff;
else if (nFrom == end)
lNewPos = m_nFileSize + lOff;
else
return -1;
if (lNewPos < 0)
AfxThrowFileException(CFileException::badSeek);
m_nPosition = lNewPos;
ASSERT_VALID(this);
return m_nPosition;
}
void CMemFile::Flush()
{
ASSERT_VALID(this);
}
void CMemFile::Close()
{
ASSERT_VALID(this);
m_nGrowBytes = 0;
m_nPosition = 0;
m_nBufferSize = 0;
m_nFileSize = 0;
if (m_lpBuffer && m_bAutoDelete)
Free(m_lpBuffer);
m_lpBuffer = NULL;
}
void CMemFile::Abort()
{
ASSERT_VALID(this);
Close();
}
void CMemFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
{
ASSERT_VALID(this);
AfxThrowNotSupportedException();
}
void CMemFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
{
ASSERT_VALID(this);
AfxThrowNotSupportedException();
}
CFile* CMemFile::Duplicate() const
{
ASSERT_VALID(this);
AfxThrowNotSupportedException();
return NULL;
}
// only CMemFile supports "direct buffering" interaction with CArchive
UINT CMemFile::GetBufferPtr(UINT nCommand, UINT nCount,
void** ppBufStart, void**ppBufMax)
{
ASSERT(nCommand == bufferCheck || nCommand == bufferCommit ||
nCommand == bufferRead || nCommand == bufferWrite);
if (nCommand == bufferCheck)
return 1; // just a check for direct buffer support
if (nCommand == bufferCommit)
{
// commit buffer
ASSERT(ppBufStart == NULL);
ASSERT(ppBufMax == NULL);
m_nPosition += nCount;
if (m_nPosition > m_nFileSize)
m_nFileSize = m_nPosition;
return 0;
}
ASSERT(nCommand == bufferWrite || nCommand == bufferRead);
ASSERT(ppBufStart != NULL);
ASSERT(ppBufMax != NULL);
// when storing, grow file as necessary to satisfy buffer request
if (nCommand == bufferWrite && m_nPosition + nCount > m_nBufferSize)
GrowFile(m_nPosition + nCount);
// store buffer max and min
*ppBufStart = m_lpBuffer + m_nPosition;
// end of buffer depends on whether you are reading or writing
if (nCommand == bufferWrite)
*ppBufMax = m_lpBuffer + min(m_nBufferSize, m_nPosition + nCount);
else
{
*ppBufMax = m_lpBuffer + min(m_nFileSize, m_nPosition + nCount);
m_nPosition += LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
}
// return number of bytes in returned buffer space (may be <= nCount)
return LPBYTE(*ppBufMax) - LPBYTE(*ppBufStart);
}
/////////////////////////////////////////////////////////////////////////////
// CMemFile diagonstics
#ifdef _DEBUG
void CMemFile::Dump(CDumpContext& dc) const
{
CFile::Dump(dc);
dc << "m_nFileSize = " << m_nFileSize;
dc << "\nm_nBufferSize = " << m_nBufferSize;
dc << "\nm_nPosition = " << m_nPosition;
dc << "\nm_nGrowBytes = " << m_nGrowBytes;
dc << "\n";
}
void CMemFile::AssertValid() const
{
CFile::AssertValid();
ASSERT((m_lpBuffer == NULL && m_nBufferSize == 0) ||
AfxIsValidAddress(m_lpBuffer, (UINT)m_nBufferSize, FALSE));
ASSERT(m_nFileSize <= m_nBufferSize);
// m_nPosition might be after the end of file, so we cannot ASSERT
// its validity
}
#endif // _DEBUG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNAMIC(CMemFile, CFile)
/////////////////////////////////////////////////////////////////////////////