/***************************************************************************
*
* File : MemoryMappedFile.h
* Author : K. Skilling
* Description : Memory mapped file wrapper class.
*
* Change History
* ---------------
* KS 7/16/99 CREATED
* KS 6/05/04 dwBytesToMap - if this is zero the entire file is mapped,
* otherwise just maps a portion
* KS 8/11/05 m_szFilePath as LPCTSTR
*****************************************************************************/
#include "MemoryMappedFile.h"
CMemoryMappedFile::CMemoryMappedFile(void)
{
_Init();
}
// KS/06/05/04 dwBytesToMap
CMemoryMappedFile::CMemoryMappedFile(LPCTSTR pszFileName,BOOL boModifiable /*=FALSE*/,DWORD dwBytesToMap /*=0*/)
{
// Given a filename, the constructor opens a file handle, creates a file
// mapping, and maps the entire file into memory.
_Init();
_OpenFile(pszFileName,boModifiable,dwBytesToMap);
}
CMemoryMappedFile::~CMemoryMappedFile(void)
{
if (eFILEOPEN != m_errCode)
_Close();
}
void CMemoryMappedFile::_Close()
{
// Clean up everything that was created by the constructor
if ( m_pMemoryMappedFileBase )
UnmapViewOfFile( m_pMemoryMappedFileBase );
if ( m_hFileMapping )
CloseHandle( m_hFileMapping );
if ( m_hFile != INVALID_HANDLE_VALUE )
CloseHandle( m_hFile );
m_errCode = eFILEOPEN;
}
BOOL CMemoryMappedFile::Close()
{
return eFILEOPEN == m_errCode ? FALSE : _Close(),TRUE;
}
// KS/06/05/04 dwBytesToMap
BOOL CMemoryMappedFile::OpenFile(LPCTSTR lpszFileName,BOOL boModifiable /*=FALSE*/,DWORD dwBytesToMap /*=0*/)
{
_OpenFile(lpszFileName,boModifiable,dwBytesToMap);
return eNOERROR == m_errCode ? TRUE : FALSE;
}
// Create a file from the null-terminated string.
BOOL CMemoryMappedFile::CreateFile(LPCTSTR pszFileName,PVOID pData,DWORD dwLen,BOOL boOverwrite /*=TRUE*/)
{
BOOL boOK = FALSE;
__try
{
SetLastError(0);
// First get a file handle
DWORD dwAccess = GENERIC_READ | GENERIC_WRITE;
DWORD dwCreate = boOverwrite ? CREATE_ALWAYS : CREATE_NEW;
m_hFile = ::CreateFile(pszFileName, dwAccess, FILE_SHARE_READ, NULL,
dwCreate, FILE_ATTRIBUTE_NORMAL,NULL);
if ( m_hFile == INVALID_HANDLE_VALUE )
{
m_errCode = eFILEOPEN;
__leave;
}
// Now, create a file mapping
// KS/10/02/2004 Allow for 0 len file - just creates it
if (dwLen > 0)
{
m_hFileMapping = ::CreateFileMapping(m_hFile,NULL,PAGE_READWRITE,0,dwLen,NULL);
if ( m_hFileMapping == 0 )
{
m_errCode = eFILEMAPPING;
__leave;
}
// Should have been 'grown' to size required so get the byte size now
m_cbFile = ::GetFileSize(m_hFile,0);
m_pMemoryMappedFileBase = (PCHAR)MapViewOfFile( m_hFileMapping,
FILE_MAP_ALL_ACCESS, 0, 0, 0);
if ( m_pMemoryMappedFileBase == 0 )
{
m_errCode = eMAPVIEW;
__leave;
}
// KS/07/05/04 - Don't necessarily have data to copy in at this point
if (pData)
::memcpy(m_pMemoryMappedFileBase,pData,dwLen);
}
m_errCode = eNOERROR;
}
__finally
{
// If any error then cleanup
if (m_errCode != eNOERROR)
{
m_dwLastError = GetLastError();
// KS/10/02/03 This is the proper test
if (INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
m_hFileMapping = 0;
}
}
return eNOERROR == m_errCode ? TRUE : FALSE;
}
void CMemoryMappedFile::_OpenFile(LPCTSTR pszFileName,BOOL boModifiable,DWORD dwBytesToMap /*=0*/)
{
BOOL boOK = FALSE;
__try
{
// KS/10/02/03 Don't want any previous error reported
SetLastError(0);
// First get a file handle
DWORD dwAccess = GENERIC_READ;
if (boModifiable) dwAccess |= GENERIC_WRITE;
m_hFile = ::CreateFile(pszFileName, dwAccess, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
if ( m_hFile == INVALID_HANDLE_VALUE )
{
m_errCode = eFILEOPEN;
__leave;
}
// Now, create a file mapping
DWORD dwProtect = boModifiable ? PAGE_READWRITE : PAGE_READONLY;
m_hFileMapping = ::CreateFileMapping(m_hFile,NULL,dwProtect, 0, 0,NULL);
if ( m_hFileMapping == 0 )
{
m_errCode = eFILEMAPPING;
__leave;
}
DWORD dwMapAccess = boModifiable ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ;
m_pMemoryMappedFileBase = (PCHAR)MapViewOfFile( m_hFileMapping,
dwMapAccess, 0, 0, dwBytesToMap);
if ( m_pMemoryMappedFileBase == 0 )
{
m_errCode = eMAPVIEW;
__leave;
}
m_cbFile = ::GetFileSize( m_hFile, 0 );
m_cbMappedSize = dwBytesToMap;
_tcscpy(m_szFilePath,pszFileName);
m_errCode = eNOERROR;
}
__finally
{
// If any error then cleanup
if (m_errCode != eNOERROR)
{
m_dwLastError = GetLastError();
if (INVALID_HANDLE_VALUE != m_hFile)
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
m_hFileMapping = 0;
}
}
}
void CMemoryMappedFile::_Init()
{
m_hFile = INVALID_HANDLE_VALUE;
m_hFileMapping = 0;
m_pMemoryMappedFileBase = 0;
m_cbFile = 0;
m_cbMappedSize = 0;
m_errCode = eFILEOPEN; // Initial error code: not found
m_dwLastError = ERROR_SUCCESS;
m_szFilePath[0] = NULL;
}