// uc_filemapping.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 tagMapInfo{
DWORD dwSizeHigh; //高位文件大小
DWORD dwSizeLow; //低位文件大小
char szMappingName[_MAX_PATH]; //映射名称
tagMapInfo()
{
dwSizeHigh = dwSizeLow = 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:
DWORD GetSize();
//////////////////////////////////////////////////
// 作者: 张旻
// 创建: 2002.01.16
// 功能: 写入映射文件
// 参数:
// [in] lpBuf 缓冲区
// [in] nSize 缓冲区大小
// [in] dwOffsetLow 偏移地址地位
// 返回:
// 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_hPhysicsFile; //物理文件句柄
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 _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//构造函数
UC_FILEMAPPING::UC_FILEMAPPING()
{
WaitForSingleObject( 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<nSizeUsed ){
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<nSize ){
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 );
}
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: %s\n", 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::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;
}
}
希望各位同仁指正.