CSDN专家博客精华版

为人民服务!
  首页  :: 新随笔  :: 管理

一个完整的共享內存类

Posted on 2007-12-17 11:25  csdnexpert  阅读(96)  评论(0编辑  收藏  举报

/******************************************************************
 ++  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 <aclapi.h>

//////////////////////////////////////////////////////////////////////
// Macro definition

// 以下為共享內存定義

#define DEFAULT_FILENAME NULL    // 默認的文件名
#define DEFAULT_MAPNAME  "_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;  // 內存文件名

 BOOL m_bOpenFlag;  // 是否已經打開了一個內存文件
 DWORD   m_dwLastError;  // 錯誤代碼
 
private:
 void _Init();    // 初始化參數
 
public:
 BOOL Open(DWORD dwAccess = FILE_MAP_READ,
  char *szMapName = DEFAULT_MAPNAME,
  DWORD dwSize = 0);      // 打開一個內存文件
 LPVOID GetBuffer();       // 獲取當前內存文件的指針
 void Destory();        // 關閉當前對內存文件的訪問

 BOOL GetCmdDataSize(DWORD *pDataSize);  // 讀取命令數據大小
 BOOL ReadCmdData(       // 讀取命令數據
  DWORD dwCommandCode,
  DWORD dwBufSize,
  LPVOID pOutBuf);
};

#endif // FZD_FFMCLASS_H

/******************************************************************
 ++  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>

//////////////////////////////////////////////////////////////////////
// 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();
}


// 創建共享內存塊
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);
  }
  if (pFileMapACL != NULL)
  {
   LocalFree(pFileMapACL);
  }
  if (pEveryoneSID != NULL)
  {
   FreeSid(pEveryoneSID);
  }
  if (pCreatorSID != NULL)
  {
   FreeSid(pCreatorSID);
  }

  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;
}



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=142999