FileMapping使用者類原始碼(原創, 歡迎批評指正) (轉)

gugu99發表於2008-01-05
FileMapping使用者類原始碼(原創, 歡迎批評指正) (轉)[@more@]

歡迎指正

// uc_filemap.h: interface for the UC_FILEMAPPING class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_)
#define AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

//////////////////////////////////////////////////
// 模組: 對映類
// 作者: 張旻
// 建立: 2002.01.16
// 說明:
//  利用記憶體對映檔案進行程式之間的記憶體共享,
//  目前的32位應用定址範圍4GB, 不需要高位
//////////////////////////////////////////////////
#include "uc_log.h"

//自定義返回值
#define RET_FILEOPENNED RET_USER + 1 //檔案已經開啟
#define RET_FILENOTOPENNED RET_USER + 2 //檔案未開啟
#define RET_BUFFERTOOBIG RET_USER + 3 //緩衝區過大
#define RET_BUFFEROVERFLOW RET_USER + 4 //緩衝區
#define RET_FILEPROCESSING RET_USER + 5 //檔案正在操作
#define RET_OFFSETOVERFLOW RET_USER + 6 //偏移量溢位

//共享記憶體的預留長度資訊結構預定義
typedef struct tagMnfo{

 D dwSizeHigh; //高位檔案大小
 DWORD dwSizeLow; //低位檔案大小

 DWORD dwSizeUsedHigh; //高位使用大小
 DWORD dwSizeUsedLow; //低位使用大小

 char szMappiame[_MAX_PATH]; //對映名稱

 tagMapInfo()
 {
 dwSizeHigh = dwSizeLow = dwSizeUsedHigh = dwSizeUsedLow = 0;
 memset( szMappingName, 0, _MAX_PATH );
 }

}US_MAPINFO, *PUS_MAPINFO;

//分頁門限
#define HIGH_MAX 0xFFFFFFFE //高位最大值
#define LOW_MAX 0xFFFFFFFF - sizeof(US_MAPINFO) //低位最大值
#define INFO_LEN sizeof(US_MAPINFO) //頭資訊長度
#define NOPHYSICALFILE 0xFFFFFFFF //不需要物理檔案

class UC_FILEMAPPING : public UC_LOG 
{
public:
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 獲得檔案使用大小
 // 引數:
 // 返回:
 //  檔案使用大小
 //////////////////////////////////////////////////
 DWORD GetSizeUsed();
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 獲得檔案大小
 // 引數:
 // 返回:
 //  檔案大小
 //////////////////////////////////////////////////
 DWORD GetSize();
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 寫入對映檔案
 // 引數:
 //  [in] lpBuf 緩衝區
 //  [in] nSize 緩衝區大小
 //  [in] dwOffsetLow 偏移地址地位
 //  [in] isAppend 追加寫入
 // 返回:
 //  RET_BADARG 引數
 //  RET_BUFFERTOBIG 快取區過大
 //  RET_BUFFEROVERFLOW 緩衝區溢位
 //  RET_FILENOTOPENNED 檔案未開啟
 //  RET_FILEPROCESSING 檔案正在操作
 //  RET_FILEERR 檔案操作失敗
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 DWORD Write( LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow=0, BOOL isAppend=TRUE );
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 讀取對映檔案
 // 引數:
 //  [in] lpBuf 緩衝區
 //  [in] nSize 緩衝區大小
 //  [in] dwOffsetLow 偏移地址地位
 // 返回:
 //  RET_BADARG 引數非法
 //  RET_BUFFERTOBIG 快取區過大
 //  RET_BUFFEROVERFLOW 緩衝區溢位
 //  RET_FILENOTOPENNED 檔案未開啟
 //  RET_FILEPROCESSING 檔案正在操作
 //  RET_FILEERR 檔案操作失敗
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 DWORD Read( LPVOID lpszBuf, UINT &nSize, DWORD dwOffsetLow=0 );
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 關閉對映檔案
 // 引數:
 //  [in] wantDump 需要匯出
 // 返回:
 //  RET_FILENOTOPENNED 檔案未開啟
 //  RET_FILEERR 檔案操作失敗
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 DWORD Close( BOOL wantDump=TRUE );
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 開啟對映檔案
 // 引數:
 //  [in] lpszMappingName 對映記憶體命名
 // 返回:
 //  RET_BADARG 引數非法
 //  RET_FILEOPENNED 檔案已經開啟
 //  RET_FILEERR 檔案操作失敗
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 DWORD Open( LPCTSTR lpszMappingName );
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 開啟對映檔案
 // 引數:
 //  [in] lpszFilePath 物理檔案路徑
 //  [in] lpszMappingName 對映記憶體命名
 //  [in] dwSizeLow 低位空間大小
 // 返回:
 //  RET_BADARG 引數非法
 //  RET_FILEOPENNED 檔案已經開啟
 //  RET_FILEERR 檔案操作失敗
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 DWORD Open( LPCTSTR lpszFilePath, LPCTSTR lpszMappingName, DWORD dwSizeLow );
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 構造
 //////////////////////////////////////////////////
 UC_FILEMAPPING();
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 解構函式
 //////////////////////////////////////////////////
 virtual ~UC_FILEMAPPING();
protected:
 HANDLE m_hPhysicile; //物理檔案控制程式碼
 HANDLE m_hMappingFile; //對映檔案控制程式碼
 HANDLE m_hFileOP; //檔案操作互斥量

 LPVOID m_lpCursor; //對映遊標地址指標
 LPVOID m_lpAddress; //對映檔案地址指標

 PUS_MAPINFO m_pusMapInfo; //對映記憶體頭資訊
 BOOL m_isFileLoaded; //工作狀態標誌
 BOOL m_isMyHandle; //是否是自己建立的檔案對映

 DWORD m_dwSysAlloc; //分配記憶體的最小單位
private:
 DWORD FlushView();
 DWORD GetErrorMessage();
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 格式化大小和偏移量
 // 引數:
 //  [in] dwOffsetLow 低位偏移量
 // 返回:
 //  RET_BADARG 引數非法
 //  RET_FILENOTOPENNED 檔案未開啟
 //  RET_FILEPROCESSING 檔案正在操作
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
 //////////////////////////////////////////////////
 // 作者: 張旻
 // 建立: 2002.01.16
 // 功能: 移動對映檔案指標
 // 引數:
 //  [in] dwOffsetLow 低位偏移量
 // 返回:
 //  RET_BADARG 引數非法
 //  RET_FILENOTOPENNED 檔案未開啟
 //  RET_FILEPROCESSING 檔案正在操作
 //  RET_OK 操作成功
 //////////////////////////////////////////////////
};

#endif // !defined(AFX_UC_FILEMAPPING_H__72FE31B2_7B02_442F_A754_66427E1C5946__INCLUDED_)

// uc_filemapping.cpp: implementation of the UC_FILEMAPPING class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "uc_filemapping.h"

#ifdef _DE
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//建構函式
UC_FILEMAPPING::UC_FILEMAPPING()
{
 WaitForSingle( m_hMutex, INFINITE );

 //初始化控制程式碼
 m_hPhysicsFile = NULL;
 m_hMappingFile = NULL;
 m_hFileOP = NULL;

 //初始化標誌
 m_isFileLoaded = FALSE;
 m_isMyHandle = FALSE;

 //初始化檔案成員變數
 m_pusMapInfo = NULL; 
 m_lpAddress = NULL;
 m_lpCursor = NULL;

 //得到系統的最小記憶體單位
 SYSTEM_INFO SysInfo;
 GetSystemInfo( &SysInfo );
 m_dwSysAlloc = SysInfo.dwAllocationGranularity;

 ReleaseMutex( m_hMutex );
}

//解構函式
UC_FILEMAPPING::~UC_FILEMAPPING()
{
 WaitForSingleObject( m_hMutex, INFINITE );

 //互斥操作
 WaitForSingleObject( m_hFileOP, INFINITE );

 //關閉對映記憶體頭資訊指標
 if ( m_pusMapInfo )
 delete m_pusMapInfo;

 //關閉控制程式碼
 ReleaseMutex( m_hFileOP );

 //只有建立者才有權關閉控制程式碼
 if ( m_isMyHandle ){
 CloseHandle( m_hPhysicsFile );
 CloseHandle( m_hMappingFile );
 CloseHandle( m_hFileOP );
 }

 ReleaseMutex( m_hMutex );
}

//新建檔案
DWORD UC_FILEMAPPING::Open(LPCTSTR lpszFilePath, LPCTSTR lpszMappingName, DWORD dwSizeLow)
{
 //狀態監測
 if ( m_isFileLoaded )
 return RET_FILEOPENNED;

 //引數監測
 if ( lpszMappingName==NULL )
 return RET_BADARG;

 DWORD dwRet = RET_OK;
 
 //建立檔案操作互斥控制程式碼
 char szMutex[_MAX_PATH];
 memset( szMutex, 0, _MAX_PATH );
 sprintf( szMutex, "%s_MUTEX", lpszMappingName );
 m_hFileOP = CreateMutex( NULL, FALSE, szMutex );
 WaitForSingleObject( m_hFileOP, INFINITE );

 //建立對應的物理檔案
 if ( lpszFilePath!=NULL ){
 
 //新建檔案
 m_hPhysicsFile = CreateFile( lpszFilePath, GENERIC_READ|GENERIC_WRITE, 0,
 NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );

 //如果檔案存在, 開啟現有檔案
 if ( m_hPhysicsFile==INVALID_HANDLE_VALUE ){
 GetErrorMessage();
 m_hPhysicsFile = CreateFile( lpszFilePath, GENERIC_READ|GENERIC_WRITE, 0,
 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
 }
 }

 if ( m_hPhysicsFile==INVALID_HANDLE_VALUE ){
 GetErrorMessage();
 m_hPhysicsFile = NULL;
 dwRet = RET_FILEERR;
 }
 else{

 //建立對映檔案(實際長度比申請長度多頭資訊的長度)
 if ( dwRet==RET_OK ){

 if ( m_hPhysicsFile==NULL ){
 m_hMappingFile = CreateFileMapping( (HANDLE)NOPHYSICALFILE, NULL, PAGE_READWRITE,
 0, dwSizeLow, lpszMappingName );
 }
 else{
 m_hMappingFile = CreateFileMapping( m_hPhysicsFile, NULL, PAGE_READWRITE,
 0, dwSizeLow + INFO_LEN, lpszMappingName );
 }

 if ( m_hMappingFile==NULL ){
 GetErrorMessage();
 CloseHandle( m_hPhysicsFile );
 m_hPhysicsFile = NULL;
 dwRet = RET_FILEERR;
 }
 else{

 //獲得對應的對映地址
 m_lpAddress = MapViewOfFile( m_hMappingFile, FILE_MAP_ALL_ACCESS,
 0, 0, 0 );
 if ( m_lpAddress==NULL ){

 dwRet = RET_FILEERR;

 }
 else{

 //儲存對映記憶體頭資訊
 if ( m_pusMapInfo==NULL )
 m_pusMapInfo = new US_MAPINFO;

 m_pusMapInfo->dwSizeLow = dwSizeLow + INFO_LEN;
 memset( m_pusMapInfo->szMappingName, 0, _MAX_PATH );
 memcpy( m_pusMapInfo->szMappingName, lpszMappingName, strlen(lpszMappingName) );
 memcpy( m_lpAddress, m_pusMapInfo, INFO_LEN );

 //儲存申請獲得的開始地址和初始化遊標資訊
 //這裡其實真正的其實地址因為包含了頭部信
 //息, 為此需要移動到空白部分
 m_lpAddress = m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + INFO_LEN );

 //設定開啟標誌資訊
 m_isFileLoaded = TRUE;
 m_isMyHandle = TRUE;

 }
 }
 }

 }

 ReleaseMutex( m_hFileOP );
 if ( dwRet!=RET_OK )
 CloseHandle( m_hFileOP );

 return dwRet;
}

//開啟一個已有命名記憶體對映檔案
DWORD UC_FILEMAPPING::Open(LPCTSTR lpszMappingName)
{
 //狀態監測
 if ( m_isFileLoaded || m_hFileOP )
 return RET_FILEOPENNED;

 //引數監測
 if ( lpszMappingName==NULL )
 return RET_BADARG;

 DWORD dwRet = RET_OK;
 
 //建立檔案操作互斥控制程式碼
 char szMutex[_MAX_PATH];
 memset( szMutex, 0, _MAX_PATH );
 sprintf( szMutex, "%s_MUTEX", lpszMappingName );
 m_hFileOP = OpenMutex( MUTEX_ALL_ACCESS, FALSE, szMutex );
 if ( m_hFileOP==NULL ){
 return RET_FILENOTOPENNED;
 }

 WaitForSingleObject( m_hFileOP, INFINITE );

 //開啟對映檔案
 m_hMappingFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, FALSE, lpszMappingName );

 if ( m_hMappingFile==NULL ){
 dwRet = RET_FILEERR;
 }
 else{

 //獲得對應的對映地址
 m_lpAddress = MapViewOfFile( m_hMappingFile, FILE_MAP_ALL_ACCESS,
 0, 0, 0 );
 if ( m_lpAddress==NULL ){
 dwRet = RET_FILEERR;
 }
 else{

 //獲得對映記憶體頭資訊
 if ( m_pusMapInfo==NULL )
 m_pusMapInfo = new US_MAPINFO;

 memcpy( m_pusMapInfo, m_lpAddress, INFO_LEN );

 //儲存地址和遊標
 //同建立時候的原理
 m_lpAddress = m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + INFO_LEN );

 //設定開啟標誌資訊
 m_isFileLoaded = TRUE;
 m_isMyHandle = TRUE;

 }
 }

 ReleaseMutex( m_hFileOP );
 return dwRet;
}

//關閉檔案
DWORD UC_FILEMAPPING::Close(BOOL wantDump)
{
 //狀態監測
 if ( m_isFileLoaded==FALSE )
 return RET_FILENOTOPENNED;

 DWORD dwRet = RET_OK;
 WaitForSingleObject( m_hFileOP, INFINITE );

 if ( wantDump )
 FlushView();

 delete m_pusMapInfo;
 m_pusMapInfo = NULL;
 m_isFileLoaded = FALSE;

 ReleaseMutex( m_hFileOP );

 //只有建立者才有權利關閉控制程式碼
 if ( m_isMyHandle==FALSE ){
 CloseHandle( m_hPhysicsFile );
 CloseHandle( m_hMappingFile );
 CloseHandle( m_hFileOP );
 }

 return dwRet;
}

//讀取對映檔案
DWORD UC_FILEMAPPING::Read(LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow )
{
 //狀態監測
 if ( m_isFileLoaded==FALSE )
 return RET_FILENOTOPENNED;

 //引數監測
 if ( lpBuf==NULL || nSize==0 )
 return RET_BADARG;

 DWORD dwRet = RET_OK;
 WaitForSingleObject( m_hFileOP, INFINITE );

 //計算內容是否溢位
 UINT nSizeUsed = (UINT)( LPBYTE(m_lpCursor) - LPBYTE(m_lpAddress) );

 if ( nSize dwRet = RET_BUFFEROVERFLOW;
 }
 else{

 //寫入資訊
 nSize = nSizeUsed;
 memcpy( lpBuf, (LPVOID)( (LPBYTE)m_lpAddress + dwOffsetLow ), nSize );

 }

 ReleaseMutex( m_hFileOP );
 return dwRet;
}

//寫入對映檔案
DWORD UC_FILEMAPPING::Write(LPVOID lpBuf, UINT &nSize, DWORD dwOffsetLow, BOOL isAppend )
{
 //狀態監測
 if ( m_isFileLoaded==FALSE )
 return RET_FILENOTOPENNED;

 //引數監測
 if ( lpBuf==NULL || nSize==0 )
 return RET_BADARG;

 DWORD dwRet = RET_OK;
 WaitForSingleObject( m_hFileOP, INFINITE );

 //計算內容是否溢位
 UINT nLeftSize = (UINT)m_pusMapInfo->dwSizeLow - (UINT)( LPBYTE(m_lpCursor) - LPBYTE(m_lpAddress) )
 - INFO_LEN;

 if ( nLeftSize dwRet = RET_BUFFEROVERFLOW;
 }
 else{

 //根據移動遊標
 if ( isAppend==FALSE ){
 m_lpCursor = (LPVOID)( (LPBYTE)m_lpAddress + dwOffsetLow );
 }

 //寫入資訊
 memcpy( m_lpCursor, lpBuf, nSize );

 //移動遊標
 if ( isAppend )
 m_lpCursor = (LPVOID)( (LPBYTE)m_lpCursor + nSize );

 //記錄檔案使用情況
 m_pusMapInfo->dwSizeUsedLow = (DWORD)( (LPBYTE)m_lpCursor - (LPBYTE)m_lpAddress );
 
 }

 ReleaseMutex( m_hFileOP );
 return dwRet;
}

//獲得錯誤資訊
DWORD UC_FILEMAPPING::GetErrorMessage()
{
 DWORD dwRet = GetLastError();
 LPVOID lpMsgBuf;
 FormatMessage(
 FORMAT_MESSAGE_ALLOCATE_BUFFER |
 FORMAT_MESSAGE_FROM_SYSTEM |
 FORMAT_MESSAGE_IGNORE_INSERTS,
 NULL,
 dwRet,
 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
 (LPTSTR) &lpMsgBuf,
 0,
 NULL
 );
 // Process any inserts in lpMsgBuf.
 // ...
 // Display the string.
 //MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
 TRACE( "0x%08X: %sn", dwRet, lpMsgBuf );
 // Free the buffer.
 LocalFree( lpMsgBuf );
 return dwRet;

}

//得到對映檔案大小
DWORD UC_FILEMAPPING::GetSize()
{
 if ( m_isFileLoaded==FALSE )
 return RET_FILENOTOPENNED;

 if ( m_pusMapInfo )
 return m_pusMapInfo->dwSizeLow - INFO_LEN;
 else
 return -1;
}

//得到對映檔案使用大小
DWORD UC_FILEMAPPING::GetSizeUsed()
{
 if ( m_isFileLoaded==FALSE )
 return RET_FILENOTOPENNED;

 if ( m_pusMapInfo )
 return m_pusMapInfo->dwSizeUsedLow;
 else
 return -1;
}

//輸出內容
DWORD UC_FILEMAPPING::FlushView()
{
 //狀態監測
 if ( m_isFileLoaded ){

 if ( m_lpCursor > m_lpAddress && m_hPhysicsFile ){
 
 SIZE_T nSize = (SIZE_T)( (LPBYTE)m_lpCursor - (LPBYTE)m_lpAddress );

 if ( FlushViewOfFile( m_lpAddress, nSize ) )
 return RET_OK;
 else
 return RET_FILEERR;

 }
 return RET_OK;

 }
 else{
 return RET_FILENOTOPENNED;
 }
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-996493/,如需轉載,請註明出處,否則將追究法律責任。

相關文章