进程间通讯 MemryMap

来源:互联网 发布:智商低怎么办知乎 编辑:程序博客网 时间:2024/06/05 20:30
class CMemMapFile
{
public:

  class CMemMapCriticalSection : public ATL::CCriticalSection
  {
  public:
  //Constructors
  #if (_WIN32_WINNT >= 0x0403)
 explicit CMemMapCriticalSection(ULONG nSpinCount) : ATL::CCriticalSection(nSpinCount)
 {
 }
  #endif
  
  //Methods
 HRESULT Lock()
 {
 Enter();
 return S_OK;
 }
 
 HRESULT Unlock() throw()
 {
 Leave();
 return S_OK;
 }
  };


  CMemMapFile(ULONG nSpinCount = 2000) : m_hFile(INVALID_HANDLE_VALUE), 
                                         m_hMapping(NULL), 
                                         m_lpData(NULL), 
                                       #if (_WIN32_WINNT >= 0x0403)
                                         m_cs(nSpinCount),
                                       #endif
                                         m_hMutex(NULL)
  {
  }


  virtual ~CMemMapFile()
  {
    UnMap();
  }


//Methods
  BOOL MapFile(LPCTSTR pszFilename, BOOL bReadOnly = FALSE, DWORD dwShareMode = 0, LPCTSTR pszMappingName = NULL, LPCTSTR pszMutexName = NULL, BOOL bGrowable = FALSE, 
               const unsigned __int64& dwStartOffset=0, const SIZE_T& nNumberOfBytesToMap=0, LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL, BOOL bNoCache = FALSE)
  {
    //Validate our parameters
    ATLASSERT(m_hFile == INVALID_HANDLE_VALUE); //Should not be already open
    ATLASSERT(m_hMapping == NULL);
    ATLASSERT(m_lpData == NULL);
    ATLASSERT(m_hMutex == NULL);
    
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);


    //Open the real file on the file system
    m_hFile = CreateFile(pszFilename, bReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, dwShareMode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (m_hFile == INVALID_HANDLE_VALUE)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to CreateFile, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Make the file sparse, if requested to make the memory mapped file growable
    if (bGrowable)
    {
      DWORD dwBytesReturned = 0;
      if (!DeviceIoControl(m_hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwBytesReturned, NULL))
      {
        DWORD dwError = GetLastError();
        ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to make file sparse, You need Windows 2000 or later and an NTFS 5 volume for this!, Error:%d\n"), dwError);
        UnMap();
        SetLastError(dwError);
        return FALSE;
      }
    }


    //Create the file mapping object
    DWORD dwFileMappingFlags = bReadOnly ? PAGE_READONLY : PAGE_READWRITE;
    if (bNoCache)
      dwFileMappingFlags |= SEC_NOCACHE;
    m_hMapping = CreateFileMapping(m_hFile, lpSecurityAttributes, dwFileMappingFlags, 0, 0, pszMappingName);
    if (m_hMapping == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to CreateFileMapping, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Map the view
    m_lpData = MapViewOfFile(m_hMapping, bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, static_cast<DWORD>((dwStartOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(dwStartOffset & 0xFFFFFFFF), nNumberOfBytesToMap);
    if (m_lpData == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Create the mutex to provide synchronised access to the mapping
    m_hMutex = CreateMutex(lpSecurityAttributes, FALSE, pszMutexName);
    if (m_hMutex == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to CreateMutex, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }
  
    return (m_lpData != NULL);
  }


  BOOL MapMemory(LPCTSTR pszMappingName, LPCTSTR pszMutexName, const SIZE_T& nBytes, BOOL bReadOnly = FALSE, LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL, BOOL bNoCache = FALSE)
  {
    //Validate our parameters
    ATLASSERT(m_hMapping == NULL);
    ATLASSERT(m_lpData == NULL);
    ATLASSERT(m_hMutex == NULL);


    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);


    //Create the file mapping object
    DWORD dwFileMappingFlags = bReadOnly ? PAGE_READONLY : PAGE_READWRITE;
    if (bNoCache)
      dwFileMappingFlags |= SEC_NOCACHE;
    m_hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, lpSecurityAttributes, dwFileMappingFlags, static_cast<DWORD>((nBytes & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(nBytes & 0xFFFFFFFF), pszMappingName);
    if (m_hMapping == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapMemory, Failed in call to CreateFileMapping, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Map the view
    m_lpData = MapViewOfFile(m_hMapping, bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, 0, nBytes);
    if (m_lpData == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Create the mutex to sync access
    m_hMutex = CreateMutex(lpSecurityAttributes, FALSE, pszMutexName);
    if (m_hMutex == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapMemory, Failed in call to CreateMutex, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    return (m_lpData != NULL);
  }


  BOOL MapExistingMemory(LPCTSTR pszMappingName, LPCTSTR pszMutexName, const SIZE_T& nBytes, BOOL bReadOnly = FALSE, BOOL bInheritHandle = FALSE, LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL)
  {
    //Validate our parameters
    ATLASSERT(m_hMapping == NULL);
    ATLASSERT(m_lpData == NULL);
    ATLASSERT(m_hMutex == NULL);
    
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);
  
    //Open the file mapping object
    DWORD dwDesiredAccess = bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE;
    m_hMapping = OpenFileMapping(dwDesiredAccess, bInheritHandle, pszMappingName);
    if (m_hMapping == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapExistingMemory, Failed in call to OpenFileMapping, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Map the view
    m_lpData = MapViewOfFile(m_hMapping, dwDesiredAccess, 0, 0, nBytes);
    if (m_lpData == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapExistingMemory, Failed in call to MapViewOfFile, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    //Create the mutex to sync access
    m_hMutex = CreateMutex(lpSecurityAttributes, FALSE, pszMutexName);
    if (m_hMutex == NULL)
    {
      DWORD dwError = GetLastError();
      ATLTRACE(_T("CMemMapFile::MapExistingMemory, Failed in call to CreateMutex, Error:%d\n"), dwError);
      UnMap();
      SetLastError(dwError);
      return FALSE;
    }


    return (m_lpData != NULL);
  }


  void UnMap()
  {
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);
  
    //Close any views which may be open
 if (m_hMutex != NULL)
 {
 ReleaseMutex(m_hMutex);
 CloseHandle(m_hMutex);
 m_hMutex = NULL;
 }


    //unmap the view
 if (m_lpData != NULL)
 {
 FlushViewOfFile(m_lpData, 0);
 UnmapViewOfFile(m_lpData);
 m_lpData = NULL;
 }


    //remove the file mapping
 if (m_hMapping != NULL)
 {
 CloseHandle(m_hMapping);
 m_hMapping = NULL;
 }


    //close the file system file if its open
 if (m_hFile != INVALID_HANDLE_VALUE)
 {
 CloseHandle(m_hFile);
 m_hFile = INVALID_HANDLE_VALUE;
 }
  }


  LPVOID Open(DWORD dwTimeout = INFINITE)
  {
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);
  
    //Validate our parameters
    if (m_lpData == NULL)
    {
      SetLastError(ERROR_INVALID_FUNCTION);
      return NULL;
    }


    //Synchronise access to the MMF using the named mutex
    return (WaitForSingleObject(m_hMutex, dwTimeout) == WAIT_OBJECT_0) ? m_lpData : NULL;
  }


  BOOL Close()
  {
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);


    //Validate our parameters
    ATLASSUME(m_hMutex != NULL); //Mutex should be valid


    return ReleaseMutex(m_hMutex);
  }


  BOOL Flush()
  {
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);
  
    //No mapping open, so nothing to do
    if (m_lpData == NULL)
    {
      SetLastError(ERROR_INVALID_FUNCTION);
 return FALSE;
    }


    return FlushViewOfFile(m_lpData, 0);
  }
  
//Accessors
  HANDLE GetFileHandle()
  { 
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);


    return m_hFile; 
  }
  
  HANDLE GetFileMappingHandle()
  { 
    //Serialize access to our member variables
    ATL::CComCritSecLock<CMemMapCriticalSection> sl(m_cs);
  
    return m_hMapping; 
  }


protected:
//Member variables
  HANDLE                 m_hFile;
  HANDLE                 m_hMapping;
  LPVOID                 m_lpData;
  HANDLE                 m_hMutex;
  CMemMapCriticalSection m_cs;
};