Интерфейс:

// MemMapFile.h - interface of the CMemMapFile class

// Copyright (c) 2004-2008 by Elijah Zarezky,
// All rights reserved.

#if !defined(__MemMapFile_h)
#define __MemMapFile_h

#if defined(_MSC_VER) && (_MSC_VER > 1000)
#pragma once
#endif   // _MSC_VER

class CMemMapFile: public CObject
{
   DECLARE_DYNAMIC(CMemMapFile)

// construction/destruction
public:
   CMemMapFile(void);
   virtual ~CMemMapFile(void);

// operations
public:
   void* Create(LPCTSTR pszFileName, BOOL fWritable, DWORD cbMaxSize = 0, LPCTSTR pszObjName = NULL);
   void* Open(BOOL fWritable, LPCTSTR pszObjName);
   void Close(void);
   void Flush(void);
   void* GetDataPtr(void);
   DWORD GetLength(void);

// attributes
public:
   CString m_strFileName;
   HANDLE m_hFile;
   CString m_strObjName;
   HANDLE m_hMapping;
   void* m_dataPtr;

// diagnostic services
#if defined(_DEBUG)
public:
   virtual void AssertValid(void) const;
   virtual void Dump(CDumpContext& dumpCtx) const;
#endif
};

#endif	// __MemMapFile_h

Реализация:

// MemMapFile.cpp - implementation of the CMemMapFile class

// Copyright (c) 2004-2008 by Elijah Zarezky,
// All rights reserved.

#include "MemMapFile.h"
#include "Win32Error.h"

#if defined(__INTEL_COMPILER)
// remark #171: invalid type conversion
#pragma warning(disable: 171)
// remark #279: controlling expression is constant
#pragma warning(disable: 279)
#endif   // __INTEL_COMPILER

#if defined(_DEBUG)
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif   // _DEBUG

// object model
IMPLEMENT_DYNAMIC(CMemMapFile, CObject)

CMemMapFile::CMemMapFile(void):
m_hFile(INVALID_HANDLE_VALUE),
m_hMapping(NULL),
m_dataPtr(NULL)
{
}

CMemMapFile::~CMemMapFile(void)
{
   Close();
}

void* CMemMapFile::Create(LPCTSTR pszFileName, BOOL fWritable, DWORD cbMaxSize, LPCTSTR pszObjName)
{
   ASSERT(m_hFile == INVALID_HANDLE_VALUE);
   ASSERT(m_hMapping == NULL);
   ASSERT(m_dataPtr == NULL);

   ASSERT(AfxIsValidString(pszFileName));
   ASSERT(::lstrlen(pszFileName) > 0);

   DWORD fdwMode = fWritable ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ;
   m_hFile = ::CreateFile(pszFileName, fdwMode, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
   if (m_hFile == INVALID_HANDLE_VALUE)
   {
      DWORD dwErrCode = ::GetLastError();
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }
   else if (cbMaxSize == 0 && ::GetFileSize(m_hFile, NULL) == 0)
   {
      // special case - zero-length file and no growing allowed
      ::CloseHandle(m_hFile);
      m_hFile = INVALID_HANDLE_VALUE;
      return (NULL);
   }

   DWORD fdwProtect = fWritable ? PAGE_READWRITE : PAGE_READONLY;
   m_hMapping = ::CreateFileMapping(m_hFile, NULL, fdwProtect, 0, cbMaxSize, pszObjName);
   if (m_hMapping == NULL)
   {
      DWORD dwErrCode = ::GetLastError();
      ::CloseHandle(m_hFile);
      m_hFile = INVALID_HANDLE_VALUE;
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }

   DWORD fdwAccess = fWritable ? FILE_MAP_WRITE : FILE_MAP_READ;
   m_dataPtr = ::MapViewOfFile(m_hMapping, fdwAccess, 0, 0, 0);
   if (m_dataPtr == NULL)
   {
      DWORD dwErrCode = ::GetLastError();
      ::CloseHandle(m_hMapping);
      m_hMapping = NULL;
      ::CloseHandle(m_hFile);
      m_hFile = INVALID_HANDLE_VALUE;
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }

   m_strFileName = pszFileName;
   m_strObjName = pszObjName;

   return (m_dataPtr);
}

void* CMemMapFile::Open(BOOL fWritable, LPCTSTR pszObjName)
{
   ASSERT(m_hFile == INVALID_HANDLE_VALUE);
   ASSERT(m_hMapping == NULL);
   ASSERT(m_dataPtr == NULL);

   ASSERT(AfxIsValidString(pszObjName));
   ASSERT(::lstrlen(pszObjName) > 0);

   DWORD fdwAccess = fWritable ? FILE_MAP_WRITE : FILE_MAP_READ;

   m_hMapping = ::OpenFileMapping(fdwAccess, FALSE, pszObjName);
   if (m_hMapping == NULL)
   {
      DWORD dwErrCode = ::GetLastError();
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }

   m_dataPtr = ::MapViewOfFile(m_hMapping, fdwAccess, 0, 0, 0);
   if (m_dataPtr == NULL)
   {
      DWORD dwErrCode = ::GetLastError();
      ::CloseHandle(m_hMapping);
      m_hMapping = NULL;
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }

   m_strObjName = pszObjName;

   return (m_dataPtr);
}

void CMemMapFile::Close(void)
{
   if (m_dataPtr != NULL)
   {
      ::UnmapViewOfFile(m_dataPtr);
      m_dataPtr = NULL;
      ::CloseHandle(m_hMapping);
      m_hMapping = NULL;
      if (m_hFile != INVALID_HANDLE_VALUE)
      {
         ::CloseHandle(m_hFile);
         m_hFile = INVALID_HANDLE_VALUE;
      }
      m_strObjName.Empty();
      m_strFileName.Empty();
   }
}

void CMemMapFile::Flush(void)
{
   ASSERT(m_dataPtr != NULL);

   if (!::FlushViewOfFile(m_dataPtr, 0))
   {
      DWORD dwErrCode = ::GetLastError();
      CWin32Error* pXcpt = new CWin32Error(dwErrCode);
      throw pXcpt;
   }
}

void* CMemMapFile::GetDataPtr(void)
{
   return (m_dataPtr);
}

DWORD CMemMapFile::GetLength(void)
{
   return (m_hFile != INVALID_HANDLE_VALUE ? ::GetFileSize(m_hFile, NULL) : 0);
}

#if defined(_DEBUG)

void CMemMapFile::AssertValid(void) const
{
   // first perform inherited validity check...
   CObject::AssertValid();

   // ...and then verify our own state as well
}

void CMemMapFile::Dump(CDumpContext& dumpCtx) const
{
   try
   {
      // first invoke inherited dumper...
      CObject::Dump(dumpCtx);

      // ...and then dump own unique members
      dumpCtx << "m_strFileName = " << m_strFileName << "\n";
      dumpCtx << "m_hFile = " << m_hFile << "\n";
      dumpCtx << "m_strObjName = " << m_strObjName << "\n";
      dumpCtx << "m_hMapping = " << m_hMapping << "\n";
      dumpCtx << "m_dataPtr = " << m_dataPtr;
   }
   catch (CFileException* pXcpt)
   {
      pXcpt->ReportError();
      pXcpt->Delete();
   }
}

#endif   // _DEBUG

Пример использования:

bool fSame = true;

CMemMapFile mmfOld;
CMemMapFile mmfNew;

try
{
   void* pvOldData = mmfOld.Create(_T("C:\\old.txt"), FALSE);
   DWORD cbOldSize = mmfOld.GetLength();
   void* pvNewData = mmfNew.Create(_T("C:\\new.txt"), FALSE);
   DWORD cbNewSize = mmfNew.GetLength();
   if (cbOldSize != cbNewSize)
   {
      fSame = false;
   }
   else
   {
      fSame = memcmp(pvOldData, pvNewData, cbOldSize) == 0;
   }
}
catch (CWin32Error* pXcpt)
{
   pXcpt->ReportError();
   delete pXcpt;
}
обновлено
26.07.2007
 
Проверка PR и ТИЦ