본문 바로가기

Windows/MFC

global memory CreateFileMapping MapViewOfFile

//
// DATE    : August 17, 2007 10:23:54
// CODER : aucd29(ccd@apsat.co.kr)
// URL     : http://www.apsat.co.kr
//
// Copyright Asia pasific satellite industries Co., Ltd.
//
// -----------------------------------------------------------
// NOTE : August 17, 2007 10:23:55
// -----------------------------------------------------------
// * devpia 에 존재하는 process 간 global memory 사용을 생성
//
// * Define
// CGlobalMem m_objGM;
//
// * Create
// m_objGM.CreateMemMap(_T("test"), 600);
//
// * Open
// m_objGM.OpenMemMap(_T("test"));
//
// * Write
// m_objGM

#include "StdAfx.h"
#include "GlobalMem.h"

#include <assert.h>

CGlobalMem::CGlobalMem(DWORD dwOption)
    : m_nHeaderSize(sizeof(DWORD))
    , m_dwSize(0)
    , m_hMemMap(NULL)
    , m_pMemMap(NULL)
    , m_hMutex(NULL)
    , m_dwTimeOut(dwOption)
{
    
}

CGlobalMem::~CGlobalMem(void)
{
    Release();
}

bool CGlobalMem::CreateMemMap(LPCTSTR pszName, DWORD dwSize, DWORD dwAccess)
{
    //
    // not file mapping
    //
    assert(pszName && dwSize && !m_hMemMap);
    Release();

    m_hMemMap = ::CreateFileMapping(
        LongToHandle(0xFFFFFFFF),            // default value
        NULL,                                // security properties
        dwAccess,                            // read/write properties
        0,                                    // check 64bit address
        dwSize + m_nHeaderSize,                // low level 32bit (LPBYTE)
        pszName);                            // shared file name (attention! unique filename)

    if (!m_hMemMap)
    {
        return false;
    }

    if (dwAccess == PAGE_READONLY)
    {
        dwAccess = FILE_MAP_READ;
    }
    else
    {
        dwAccess = FILE_MAP_WRITE;
    }

    if (::GetLastError() == ERROR_ALREADY_EXISTS)
    {
        m_pMemMap = ::MapViewOfFile(
            m_hMemMap,                // handle of file map
            dwAccess,                // access mode
            0,0,0);                    // high mem addr(start addr), low mem addr(start addr)
                                    // memory block size (0 == full memory map)

        if (!m_pMemMap)
        {
            return false;
        }

        // get memory info
        memcpy(&m_dwSize, m_pMemMap, m_nHeaderSize);

        CString szMutex;
        szMutex.Format(_T("Mutex of %s"), pszName);        
        m_hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, false, (LPCTSTR)szMutex);

        TRACE(L"[DEBUG] EXIST MUTEX OPEN\n");
        return true;
    }

    m_pMemMap = ::MapViewOfFile(
        m_hMemMap,            // handle of file
        dwAccess,            // access mode (this write)
        0,0,0);

    if (!m_pMemMap)
    {
        return false;
    }

    // initialize memory area
    memset(m_pMemMap, 0, dwSize + m_nHeaderSize);    // initialize
    m_dwSize = dwSize;
    memcpy(m_pMemMap, &dwSize, m_nHeaderSize);        // set memory map info

    CString szMutex;
    szMutex.Format(_T("Mutex of %s"), pszName);        
    m_hMutex = ::CreateMutex(NULL, false, (LPCTSTR)szMutex);

    return true;
}

bool CGlobalMem::OpenMemMap(LPCTSTR pszName, DWORD dwAccess)
{
    assert(pszName && dwAccess && !m_hMemMap);

    m_hMemMap = ::OpenFileMapping(dwAccess, false, pszName);
    if (!m_hMemMap)
    {
        AfxMessageBox(L"error open file mapping");
        return false;
    }

    m_pMemMap = ::MapViewOfFile(m_hMemMap, dwAccess, 0, 0, 0);

    if (!m_pMemMap)
    {
        return false;
    }

    memcpy(&m_dwSize, m_pMemMap, m_nHeaderSize);

    CString szMutex;
    szMutex.Format(_T("Mutex of %s"), pszName);        
    m_hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, false, (LPCTSTR)szMutex);

    return true;
}

void CGlobalMem::Release(void)
{
    if (m_pMemMap)
    {
        ::UnmapViewOfFile(m_pMemMap);
    }

    if (m_hMemMap)
    {
        ::CloseHandle(m_hMemMap);
    }

    m_hMemMap = 0;
    m_pMemMap = 0;

    if (m_hMutex)
    {
        ::CloseHandle(m_hMutex);
    }
    m_hMutex = 0;
}

int CGlobalMem::Write(LPVOID pData, UINT nStart, UINT nCount)
{
    assert(nStart + m_nHeaderSize < m_dwSize);

    TCHAR* pStart = (TCHAR*)pData;
    if (!nCount)
    {
        nCount = (UINT)_tcslen(pStart);
    }

    TRACE(L"[DEBUG][Write] nCount:%d, m_dwSize:%d, nStart:%d\n", nCount,m_dwSize,nStart);
    if (nCount > (m_dwSize - nStart))
    {
        nCount -= (nCount - (m_dwSize - nStart));
    }

    if (pData)
    {
        if (m_hMutex)
        {
            if (::WaitForSingleObject(m_hMutex, m_dwTimeOut) == WAIT_FAILED)
            {
                return -1;
            }
        }

        TRACE(L"[DEBUG][Write] m_nHeaderSize:%d\n", m_nHeaderSize);
        void* pR = memcpy((TCHAR*)m_pMemMap + nStart + m_nHeaderSize, pData, nCount);

        if (m_hMutex)
        {
            if (!::ReleaseMutex(m_hMutex))
            {
                CloseHandle(m_hMutex);
                m_hMutex = 0;
            }
        }

        //
        // Error
        //
        if (pR == 0)
        {
            return -1;
        }
    }
    else
    {
        //
        // Clean
        //
        memset((TCHAR*)m_pMemMap + nStart + m_nHeaderSize, 0, nCount);
    }
    
    return nCount;
}

int CGlobalMem::Read(LPVOID pData, UINT nStart, UINT nCount)
{
    assert(nStart + m_nHeaderSize < m_dwSize && pData);

    //
    // check range
    //
    if (!nCount)
    {
        nCount = m_dwSize;
    }
    
    TRACE(L"[DEBUG][Read] nCount:%d, m_dwSize:%d, nStart:%d\n", nCount, m_dwSize, nStart);
    if (nCount > m_dwSize - nStart)
    {
        nCount -= (nCount - (m_dwSize - nStart));
    }

    if (!memcpy(pData, (TCHAR*)m_pMemMap + nStart + m_nHeaderSize, nCount))
    {
        return -1;
    }

    return nCount;
}

HANDLE CGlobalMem::GetHandle(void)
{
    return m_hMemMap;
}

LPVOID CGlobalMem::GetPtr(void)
{
    return m_pMemMap;
}

DWORD CGlobalMem::GetSize(void)
{
    return m_dwSize;
}

DWORD CGlobalMem::GetTimeOut(void)
{
    return m_dwTimeOut;
}

void CGlobalMem::SetTimeout(DWORD dwTime)
{
    m_dwTimeOut = dwTime;
}


[code]header[/code]

#pragma once

class CGlobalMem
{
public:
    CGlobalMem(DWORD dwOption=INFINITE);
    ~CGlobalMem(void);

protected:
    DWORD m_dwTimeOut;
    HANDLE m_hMutex, m_hMemMap;
    LPVOID m_pMemMap;
    const int m_nHeaderSize;
    DWORD m_dwSize;

public:
    bool CreateMemMap(LPCTSTR pszName, DWORD dwSize, DWORD dwAccess=PAGE_READWRITE);
    bool OpenMemMap(LPCTSTR pszName, DWORD dwAccess=FILE_MAP_ALL_ACCESS);
    void Release(void);
    int Write(LPVOID pData, UINT nStart=0, UINT nCount=0);
    int Read(LPVOID pData, UINT nStart=0, UINT nCount=0);
    HANDLE GetHandle(void);
    LPVOID GetPtr(void);
    DWORD GetSize(void);
    DWORD GetTimeOut(void);
    void SetTimeout(DWORD dwTime);
};

'Windows > MFC' 카테고리의 다른 글

Environments information path (registry)  (0) 2013.10.02
CButtonMenu  (0) 2013.10.02
Displaying the Installed Devices  (0) 2013.10.02
Creating named shared Memory  (0) 2013.10.02
expand dialog  (0) 2013.10.02