忘记是从哪里整理的一个类了,但非常好用,可以将其放在自己的项目中实现不同进程间数据的通信。
头文件:
[cpp] view plaincopy
/******************************************************************
++ File Name : FFMClass.h
++ Description: 共享內存類
---------------------------------------------------------------
++ Author: Fei ZhaoDong
++ Create time: 2004/3/25 上午 10:00:00
++ Version: 1.1
++ Modifier:
++ Activities:
++ Update List: 2004/3/30 下午 02:59:45
*******************************************************************/
// FFMClass.h: interface for the CFFMClass.
//
//////////////////////////////////////////////////////////////////////
#ifndef FZD_FFMCLASS_H
#define FZD_FFMCLASS_H
//#include <Winbase.h>
#include <aclapi.h>
//////////////////////////////////////////////////////////////////////
// Macro definition
// 以下為共享內存定義
#define DEFAULT_FILENAME NULL // 默認的文件名
#define DEFAULT_MAPNAME "Local//_FZD_MAP_" // 默認的共享內存名
#define DEFAULT_MAPSIZE (0xFFFF + 1) // 默認的共享內存大小
const DWORD NETRGUSER_CFM_CODE = 0x1211DBFF; // 校驗碼, 用於命令數據
const DWORD NETRGUSER_CMD_NONE = 0; // 初始化指令碼, 無指令
// 以下為錯誤碼定義
#define ERROR_LEN 256 // 錯誤描述長度
#define ERROR_INVALID_CMDCODE 0xE00001FF // 已經存在完全一樣的共享內存
#define ERROR_NO_MAPFILE 0xE00002FF // 未分配共享內存文件
#define ERROR_INVALID_CFMCODE 0xE00003FF // 校驗碼不匹配
//////////////////////////////////////////////////////////////////////
// 內存文件格式定義
#pragma pack(1)
// 用於存儲命令數據的內存文件格式
typedef struct _tagDATA_HEADER
{
DWORD dwConfirmCode; // 校驗碼
DWORD nCommandCode; // 指令識別碼
DWORD dwDataSize; // 數據的大小
BYTE dwReserved[19]; // 保留
BYTE bInfo[1]; // 數據起始地址
_tagDATA_HEADER()
{
dwConfirmCode = NETRGUSER_CFM_CODE;
nCommandCode = NETRGUSER_CMD_NONE;
dwDataSize = 0;
ZeroMemory(dwReserved, 19);
ZeroMemory(bInfo, 1);
}
}DATA_HEADER, *LPDATA_HEADER;
typedef DWORD (WINAPI *PSetEntriesInAcl)(ULONG, PEXPLICIT_ACCESS, PACL, PACL*);
// 用於存儲應答數據的共享內存文件格式 (暫不用)
typedef struct _tagANS_HEADER
{
}ANS_HEADER, *LPANS_HEADER;
#pragma pack()
//////////////////////////////////////////////////////////////////////
// 類定義,共享內存服務端
class CFFMServer
{
public:
CFFMServer();
virtual ~CFFMServer();
CFFMServer(char *szFileName, char *szMapName, DWORD dwSize);
protected:
PSetEntriesInAcl m_fnpSetEntriesInAcl;
HANDLE m_hFile; // 映射文件句柄
HANDLE m_hFileMap; // 內存文件句柄
LPVOID m_lpFileMapBuffer; // 緩衝區指針
char *m_pFileName; // 映射文件名
char *m_pMapName; // 內存文件名
DWORD m_dwSize; // 緩衝區大小
BOOL m_bCreateFlag; // 是否已創建共享內存
DWORD m_dwLastError; // 錯誤代碼
private:
void _Init(); // 初始化參數
BOOL _IsWinNTLater(); // 判斷當前操作系統
public:
BOOL Create(char *szFileName = DEFAULT_FILENAME,
char *szMapName = DEFAULT_MAPNAME,
DWORD dwSize = DEFAULT_MAPSIZE); // 新建共享內存
LPVOID GetBuffer(); // 獲取內存文件指針
DWORD GetSize(); // 獲取內存文件大小
void Destory(); // 銷毀已有的共享內存
BOOL WriteCmdData( // 寫入命令數據
DWORD nCommandCode,
DWORD dwDataSize,
const LPVOID pBuf);
};
//////////////////////////////////////////////////////////////////////
// 類定義,共享內存客戶端
class CFFMClient
{
public:
CFFMClient();
virtual ~CFFMClient();
CFFMClient(DWORD dwAccess, char *szMapName, DWORD dwSize);
protected:
HANDLE m_hFileMap; // 內存文件句柄
LPVOID m_lpFileMapBuffer; // 內存文件指針
char *m_pMapName; // 內存文件名
DWORD m_dwSize; // 緩衝區大小
BOOL m_bOpenFlag; // 是否已經打開了一個內存文件
DWORD m_dwLastError; // 錯誤代碼
private:
void _Init(); // 初始化參數
public:
BOOL Open(DWORD dwAccess = FILE_MAP_READ | FILE_MAP_WRITE,
char *szMapName = DEFAULT_MAPNAME,
DWORD dwSize = 0); // 打開一個內存文件
LPVOID GetBuffer(); // 獲取當前內存文件的指針
void Destory(); // 關閉當前對內存文件的訪問
DWORD GetSize(); // 獲取內存文件大小
BOOL GetCmdDataSize(DWORD *pDataSize); // 讀取命令數據大小
BOOL ReadCmdData( // 讀取命令數據
DWORD dwCommandCode,
DWORD dwBufSize,
LPVOID pOutBuf);
BOOL WriteCmdData( // 寫入命令數據
DWORD memSize,
DWORD nCommandCode,
DWORD dwDataSize,
const LPVOID pBuf);
};
#endif // FZD_FFMCLASS_H
实现文件:
[cpp] view plaincopy
/******************************************************************
++ File Name : FFMClass.cpp
++ Description: 共享內存類
---------------------------------------------------------------
++ Author: Fei ZhaoDong
++ Create time: 2004/3/25 上午 10:00:00
++ Version: 1.0
++ Modifier:
++ Activities:
++ Update List: 2004/3/29 下午 02:59:45
*******************************************************************/
// FFMClass.cpp: implementation of the CFFMClass.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FFMClass.h"
//#include <aclapi.h>
//#include <windows.h>
//#include <aclapi.h>
//#include <lmerr.h>
//
//#include <stdio.h>
//////////////////////////////////////////////////////////////////////
// CFFMServer
//////////////////////////////////////////////////////////////////////
CFFMServer::CFFMServer()
{
m_dwLastError = 0;
m_fnpSetEntriesInAcl = NULL;
_Init();
}
CFFMServer::~CFFMServer()
{
Destory();
}
CFFMServer::CFFMServer(char *szFileName, char *szMapName, DWORD dwSize)
{
// 以自定義設置創建共享內存塊
_Init();
Create(szFileName, szMapName, dwSize);
}
// 初始化各個參數
void CFFMServer::_Init()
{
m_hFile = NULL;
m_hFileMap = NULL;
m_lpFileMapBuffer = NULL;
m_pFileName = NULL;
m_pMapName = NULL;
m_dwSize = 0;
m_bCreateFlag = FALSE;
}
// 判斷是否NT4.0以上操作系統
BOOL CFFMServer::_IsWinNTLater()
{
OSVERSIONINFO Ver;
BOOL bAbleVersion = FALSE;
Ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&Ver))
{
if (Ver.dwPlatformId == VER_PLATFORM_WIN32_NT
&& Ver.dwMajorVersion >= 4)
{
bAbleVersion = TRUE;
}
}
else
{
m_dwLastError = GetLastError();
}
return bAbleVersion;
}
// 釋放當前共享內存,並重新初始化參數
void CFFMServer::Destory()
{
if (m_lpFileMapBuffer != NULL)
{
UnmapViewOfFile(m_lpFileMapBuffer);
m_lpFileMapBuffer = NULL;
}
if (m_hFileMap != NULL)
{
CloseHandle(m_hFileMap);
m_hFileMap = NULL;
}
if (m_hFile && m_hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hFile);
m_hFile = NULL;
}
if (m_pFileName != NULL)
{
free(m_pFileName);
m_pFileName = NULL;
}
if (m_pMapName != NULL)
{
free(m_pMapName);
m_pMapName = NULL;
}
_Init();
}
static void FreeSidEx(PSID oSID)
{
try
{
FreeSid(oSID);
}
catch(...)
{
}
}
// 創建共享內存塊
BOOL CFFMServer::Create(char *szFileName, char *szMapName, DWORD dwSize)
{
// 釋放已有的共享內存塊
if (m_bCreateFlag)
{
Destory();
}
// 拷貝各個參數
if (szFileName)
{
m_pFileName = _strdup(szFileName);
}
if (szMapName)
{
m_pMapName = _strdup(szMapName);
}
else
{
m_pMapName = _strdup(DEFAULT_MAPNAME);
}
if (dwSize > 0)
{
m_dwSize = dwSize;
}
else
{
m_dwSize = DEFAULT_MAPSIZE;
}
// 以下創建共享內存
if (m_pFileName)
{
m_hFile = CreateFile(
m_pFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
}
else
{
// 默認情況下,在頁面文件中創建共享內存
m_hFile = INVALID_HANDLE_VALUE;
}
if (_IsWinNTLater())
{
// Set DACL
const int NUM_ACES = 2; // number if ACEs int DACL
// evryone -- read
// creator -- full access
// 初始化參數
PSID pEveryoneSID = NULL; // everyone群組SID
PSID pCreatorSID = NULL; // creator群組SID
PACL pFileMapACL = NULL; // 準備新內存文件的DACL
PSECURITY_DESCRIPTOR pSD = NULL; // 內存文件的SD
SECURITY_ATTRIBUTES saFileMap; // 內存文件的SA
EXPLICIT_ACCESS ea[NUM_ACES]; // 外部訪問結構
BOOL bHasErr = FALSE; // 返回值
// 以下創建SID
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthCreator = SECURITY_CREATOR_SID_AUTHORITY;
// Evryone
if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
{
bHasErr = TRUE;
goto Finish;
}
// Creator
if (!AllocateAndInitializeSid(&SIDAuthCreator, 1, SECURITY_CREATOR_OWNER_RID,
0, 0, 0, 0, 0, 0, 0, &pCreatorSID))
{
bHasErr = TRUE;
goto Finish;
}
// 填充ACE
ZeroMemory(&ea, NUM_ACES * sizeof(EXPLICIT_ACCESS));
// S-1-1-0 evryone, 唯讀權限
ea[0].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance= NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID;
// S-1-3-0 creator owner, 完全權限
ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance= NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR) pCreatorSID;
// 創建並填充ACL
if(NULL == m_fnpSetEntriesInAcl)
{
HINSTANCE hLib = ::LoadLibrary("Advapi32.dll");
if(NULL != hLib)
{
m_fnpSetEntriesInAcl = (PSetEntriesInAcl)GetProcAddress(hLib,"SetEntriesInAclA");
::FreeLibrary(hLib);
hLib = NULL;
}
}
if (ERROR_SUCCESS != m_fnpSetEntriesInAcl(NUM_ACES, ea, NULL, &pFileMapACL))
{
bHasErr = TRUE;
goto Finish;
}
// 創建並初始化SD
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
bHasErr = TRUE;
goto Finish;
}
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
{
bHasErr = TRUE;
goto Finish;
}
// 添加ACL到SD中去
if (!SetSecurityDescriptorDacl(pSD,
TRUE, // fDaclPresent flag
pFileMapACL,
FALSE)) // not a default DACL
{
bHasErr = TRUE;
goto Finish;
}
// 設置SA
saFileMap.nLength = sizeof(SECURITY_ATTRIBUTES);
saFileMap.bInheritHandle = FALSE;
saFileMap.lpSecurityDescriptor = pSD;
// 創建共享內存文件
if (m_hFile != NULL)
{
m_hFileMap = CreateFileMapping(
m_hFile,
&saFileMap,
PAGE_READWRITE,
0,
m_dwSize,
m_pMapName);
if (NULL == m_hFileMap)
{
m_hFileMap = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
TRUE, m_pMapName);
if (NULL == m_hFileMap)
{
m_dwLastError = GetLastError();
Destory();
goto Finish;
}
}
}
Finish:
//if (pSD != NULL)
//{
// LocalFree(pSD);
//}
pSD = NULL;
if (pFileMapACL != NULL)
{
LocalFree(pFileMapACL);
pFileMapACL = NULL;
}
if (pEveryoneSID != NULL)
{
FreeSidEx(pEveryoneSID);
pEveryoneSID = NULL;
}
if (pCreatorSID != NULL)
{
FreeSidEx(pCreatorSID);
pCreatorSID = NULL;
}
if (bHasErr)
{
m_dwLastError = GetLastError();
return FALSE;
}
}
else
{
// 創建共享內存文件
if (m_hFile)
{
m_hFileMap = CreateFileMapping(
m_hFile,
NULL,
PAGE_READWRITE,
0,
m_dwSize,
m_pMapName);
if (NULL == m_hFileMap)
{
m_dwLastError = GetLastError();
Destory();
return FALSE;
}
}
}
// 映射文件指針到用戶
if (m_hFileMap)
{
m_lpFileMapBuffer = MapViewOfFile(
m_hFileMap,
FILE_MAP_ALL_ACCESS,
0,
0,
m_dwSize);
if (NULL == m_lpFileMapBuffer)
{
m_dwLastError = GetLastError();
Destory();
return FALSE;
}
}
m_bCreateFlag = TRUE;
return TRUE;
}
// 獲取內存文件指針
LPVOID CFFMServer::GetBuffer()
{
return (m_lpFileMapBuffer)?(m_lpFileMapBuffer):(NULL);
}
// 獲取內存文件大小
DWORD CFFMServer::GetSize()
{
return m_dwSize;
}
BOOL CFFMServer::WriteCmdData(DWORD nCommandCode, DWORD dwDataSize, const LPVOID pBuf)
{
// 檢驗數據的合理性
if (NULL == GetBuffer())
{
m_dwLastError = ERROR_NO_MAPFILE;
SetLastError(ERROR_NO_MAPFILE);
return FALSE;
}
if (NETRGUSER_CMD_NONE == nCommandCode)
{
m_dwLastError = ERROR_INVALID_CMDCODE;
SetLastError(ERROR_INVALID_CMDCODE);
return FALSE;
}
if (dwDataSize > 0 && pBuf == NULL)
{
m_dwLastError = ERROR_INVALID_USER_BUFFER;
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
if (dwDataSize + sizeof(DATA_HEADER) > GetSize())
{
m_dwLastError = ERROR_BUFFER_OVERFLOW;
SetLastError(ERROR_BUFFER_OVERFLOW);
return FALSE;
}
// 填寫數據結構
// 文件頭
DATA_HEADER dataHeader;
dataHeader.nCommandCode = nCommandCode;
dataHeader.dwDataSize = dwDataSize;
ZeroMemory(GetBuffer(), GetSize());
memcpy(GetBuffer(), &dataHeader, sizeof(DATA_HEADER));
// 數據塊
LPDATA_HEADER pData = (LPDATA_HEADER)GetBuffer();
memcpy(pData->bInfo, pBuf, dwDataSize);
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CFFMClient
//////////////////////////////////////////////////////////////////////
CFFMClient::CFFMClient()
{
m_dwLastError = 0;
_Init();
}
CFFMClient::~CFFMClient()
{
Destory();
}
CFFMClient::CFFMClient(DWORD dwAccess, char *szMapName, DWORD dwSize)
{
_Init();
if (!Open(dwAccess, szMapName, dwSize))
{
Destory();
}
}
// 初始化參數
void CFFMClient::_Init()
{
m_hFileMap = NULL;
m_lpFileMapBuffer = NULL;
m_pMapName = NULL;
m_bOpenFlag = FALSE;
}
// 關閉當前對內存文件的訪問
void CFFMClient::Destory()
{
if (m_lpFileMapBuffer)
{
UnmapViewOfFile(m_lpFileMapBuffer);
m_lpFileMapBuffer = NULL;
}
if (m_hFileMap)
{
CloseHandle(m_hFileMap);
m_hFileMap = NULL;
}
if (m_pMapName)
{
free(m_pMapName);
m_pMapName = NULL;
}
_Init();
}
// 打開一個內存文件
BOOL CFFMClient::Open(DWORD dwAccess, char *szMapName, DWORD dwSize)
{
if (m_bOpenFlag)
{
Destory();
}
if (szMapName != NULL)
{
m_pMapName = _strdup(szMapName);
}
else
{
m_pMapName = _strdup(DEFAULT_MAPNAME);
}
m_hFileMap = OpenFileMapping(dwAccess, TRUE, m_pMapName);
if (NULL == m_hFileMap)
{
m_dwLastError = GetLastError();
Destory();
return FALSE;
}
m_lpFileMapBuffer = MapViewOfFile(m_hFileMap, dwAccess, 0, 0, dwSize);
if (NULL == m_lpFileMapBuffer)
{
m_dwLastError = GetLastError();
Destory();
return FALSE;
}
m_bOpenFlag = TRUE;
return TRUE;
}
// 獲取當前內存文件的指針
LPVOID CFFMClient::GetBuffer()
{
return (m_lpFileMapBuffer)?(m_lpFileMapBuffer):(NULL);
}
// 讀取命令數據大小
BOOL CFFMClient::GetCmdDataSize(DWORD *pDataSize)
{
_ASSERT(pDataSize != NULL);
*pDataSize = 0;
LPDATA_HEADER pHeader = (LPDATA_HEADER)GetBuffer();
if (NULL == pHeader)
{
m_dwLastError = ERROR_NO_MAPFILE;
SetLastError(ERROR_NO_MAPFILE);
return FALSE;
}
if (NETRGUSER_CFM_CODE != pHeader->dwConfirmCode)
{
m_dwLastError = ERROR_INVALID_CFMCODE;
SetLastError(ERROR_INVALID_CFMCODE);
return FALSE;
}
if (NETRGUSER_CMD_NONE == pHeader->nCommandCode)
{
m_dwLastError = ERROR_INVALID_CMDCODE;
SetLastError(ERROR_INVALID_CMDCODE);
return FALSE;
}
*pDataSize = pHeader->dwDataSize;
return TRUE;
}
// 讀取命令數據
BOOL CFFMClient::ReadCmdData(DWORD dwCommandCode, DWORD dwBufSize, LPVOID pOutBuf)
{
_ASSERT (pOutBuf != NULL);
LPDATA_HEADER pHeader = (LPDATA_HEADER)GetBuffer();
if (NULL == pHeader)
{
m_dwLastError = ERROR_NO_MAPFILE;
SetLastError(ERROR_NO_MAPFILE);
return FALSE;
}
if (NETRGUSER_CFM_CODE != pHeader->dwConfirmCode)
{
m_dwLastError = ERROR_INVALID_CFMCODE;
SetLastError(ERROR_INVALID_CFMCODE);
return FALSE;
}
if (NETRGUSER_CMD_NONE == pHeader->nCommandCode)
{
m_dwLastError = ERROR_INVALID_CMDCODE;
SetLastError(ERROR_INVALID_CMDCODE);
return FALSE;
}
if (pHeader->dwDataSize > dwBufSize)
{
m_dwLastError = ERROR_BUFFER_OVERFLOW;
SetLastError(ERROR_BUFFER_OVERFLOW);
return FALSE;
}
if (pHeader->nCommandCode != dwCommandCode)
{
m_dwLastError = ERROR_INVALID_CMDCODE;
SetLastError(ERROR_INVALID_CMDCODE);
return FALSE;
}
ZeroMemory(pOutBuf, dwBufSize);
// 拷貝數據到緩衝區
memcpy(pOutBuf, pHeader->bInfo, pHeader->dwDataSize);
return TRUE;
}
BOOL CFFMClient::WriteCmdData(DWORD memSize, DWORD nCommandCode, DWORD dwDataSize, const LPVOID pBuf)
{
if(!memSize)
memSize = DEFAULT_MAPSIZE;
m_dwSize = memSize;
// 檢驗數據的合理性
if (NULL == GetBuffer())
{
m_dwLastError = ERROR_NO_MAPFILE;
SetLastError(ERROR_NO_MAPFILE);
return FALSE;
}
if (NETRGUSER_CMD_NONE == nCommandCode)
{
m_dwLastError = ERROR_INVALID_CMDCODE;
SetLastError(ERROR_INVALID_CMDCODE);
return FALSE;
}
if (dwDataSize > 0 && pBuf == NULL)
{
m_dwLastError = ERROR_INVALID_USER_BUFFER;
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
if (dwDataSize + sizeof(DATA_HEADER) > GetSize())
{
m_dwLastError = ERROR_BUFFER_OVERFLOW;
SetLastError(ERROR_BUFFER_OVERFLOW);
return FALSE;
}
// 填寫數據結構
// 文件頭
DATA_HEADER dataHeader;
dataHeader.nCommandCode = nCommandCode;
dataHeader.dwDataSize = dwDataSize;
ZeroMemory(GetBuffer(), GetSize());
memcpy(GetBuffer(), &dataHeader, sizeof(DATA_HEADER));
// 數據塊
LPDATA_HEADER pData = (LPDATA_HEADER)GetBuffer();
memcpy(pData->bInfo, pBuf, dwDataSize);
return TRUE;
}
// 獲取內存文件大小
DWORD CFFMClient::GetSize()
{
return m_dwSize;
}