📄 memory.cpp
字号:
// @doc
//
// @module Memory.cpp - Common Memory Object |
//
// The CCommonMemory class contains member functions that allow the
// caller to read and write the runtime data for the I/O driver
//
// Maintenance:
//
// Version Date Who What
// ------- ----------- ------ -------------------------------------
// 7.0 07/27/96 msb Created
// 01/06/97 msb added functions for nio access and block status
// 02/04/97 msb added functions for IOA access
// 02/27/97 blm Integrated EventArea from Raptor (kwr)
// Renamed Memory.h DrvMemory.h
// 05/29/98 blm Added security attributes to CreateMutex() and
// CreateEvent() so would work as a Service
//
// 7.12 12/28/99 mvs Modified CreateDataBlock() - We need to
// initialize the internal addresses else if
// this is a block which is being reused we
// could end up with the wrong internal address
//
#include "stdafx.h"
#include <stdio.h>
#include <ItkErr.h>
#include "DrvMemory.h"
//
// @mfunc <c CCommonMemory> constructor for this class. This
// constuctor creates the memory areas required for the
// shared data for the driver
//
EXPORT32 CCommonMemory::CCommonMemory( IN DWORD dwAreas, IN const TCHAR *szAppName)
{
TCHAR szAreaName[MAX_PATH],
szRegistryName[MAX_PATH];
sprintf(szRegistryName, "Software\\Intellution\\Drivers\\%s", szAppName);
//
// Initialize all our data members for this class
//
m_pDataArea = NULL;
m_pBlockList = NULL;
m_pOutputArea = NULL;
m_pExceptionArea = NULL;
m_pEventArea = NULL;
m_hDataLock = NULL;
m_hOutputLock = NULL;
m_hExceptionLock = NULL;
m_hEventLock = NULL;
m_dwHoles = 0;
//
// Initialize the Win32 security attributes structures
// Let everybody in...
//
SECURITY_ATTRIBUTES SecAttr;
SECURITY_DESCRIPTOR SecDesc;
INIT_SECURITY_ALL(SecAttr, SecDesc);
//
// Create the input area & initialize variables
//
if (dwAreas & DATA_AREA)
{
sprintf(szAreaName, "%s_InputArea", szAppName);
m_pDataArea = new CGmmf(szAppName, szRegistryName, szAreaName);
sprintf(szAreaName, "%s_InputLock", szAppName);
m_hDataLock = CreateMutex(&SecAttr, FALSE, szAreaName);
}
//
// Create the Block List area
//
if (dwAreas & BLOCK_LIST)
{
sprintf(szAreaName, "%s_BlockList", szAppName);
m_pBlockList = new CGmmf(szAppName, szRegistryName, szAreaName);
m_dwHoles = 0;
}
//
// Create the Output area & initialize variables
// Also create an event that will be triggered when someone places data
// in the output area to be written.
//
if (dwAreas & OUTPUT_AREA)
{
sprintf(szAreaName, "%s_OutputArea", szAppName);
m_pOutputArea = new CGmmf(szAppName, szRegistryName, szAreaName);
sprintf(szAreaName, "%s_OutputLock", szAppName);
m_hOutputLock = CreateMutex(&SecAttr, FALSE, szAreaName);
sprintf(szAreaName, "%s_OutputEvent", szAppName);
m_hOutputEvent = CreateEvent(&SecAttr, FALSE, FALSE, szAreaName);
}
//
// Create the exception area & initialize variables
//
if (dwAreas & EXCEPTION_AREA)
{
sprintf(szAreaName, "%s_ExceptionArea", szAppName);
m_pExceptionArea = new CGmmf(szAppName, szRegistryName, szAreaName);
sprintf(szAreaName, "%s_ExceptionLock", szAppName);
m_hExceptionLock = CreateMutex(&SecAttr, FALSE, szAreaName);
}
//
// Create the events area & initialize variables
//
if (dwAreas & EVENT_AREA)
{
sprintf(szAreaName, "%s_EventArea", szAppName);
m_pEventArea = new CGmmf(szAppName, szRegistryName, szAreaName);
sprintf(szAreaName, "%s_EventLock", szAppName);
m_hEventLock = CreateMutex(&SecAttr, FALSE, szAreaName);
}
}
//
// @mfunc <c CCommonMemory> destructor for this class. This
// destuctor deletes the memory areas required for the
// shared data for the driver
//
EXPORT32 CCommonMemory::~CCommonMemory(void)
{
// remove the four areas and the locks that were created
if (NULL != m_pDataArea)
delete m_pDataArea;
if (NULL != m_pBlockList)
delete m_pBlockList;
if (NULL != m_hDataLock)
CloseHandle(m_hDataLock);
if (NULL != m_pOutputArea)
delete m_pOutputArea;
if (NULL != m_hOutputLock)
CloseHandle(m_hOutputLock);
if (NULL != m_hOutputEvent)
CloseHandle(m_hOutputEvent);
if (NULL != m_pExceptionArea)
delete m_pExceptionArea;
if (NULL != m_hExceptionLock)
CloseHandle(m_hExceptionLock);
if (NULL != m_pEventArea)
delete m_pEventArea;
if (NULL != m_hEventLock)
CloseHandle(m_hEventLock);
}
//
// @mfunc This function creates a block for storing real time data
//
// @parm OUT LONG * | lBlockNum | Index of block number
//
// @parm IN OPTIONAL WORD | wByteSize | Number of bytes block should be
//
// @parm IN OPTIONAL DWORD | dwDataBlockHandle | Handle of DataBlock this
// memory block is being created for
//
// @rvalue Error value. ERROR_SUCCESS if successful.
//
EXPORT32 DWORD CCommonMemory::CreateDataBlock(OUT WORD *wBlockNum,
IN OPTIONAL WORD wByteSize /* = 250 */,
IN OPTIONAL DWORD dwDataBlockHandle /* = NULL */)
{
DWORD dwStatus = ERROR_SUCCESS;
// get a pointer to the list of blocks
DATA_AREA_LINK *pBlockLink,// = (DATA_AREA_LINK *)m_pBlockList->GetAddress(),
*pPrevBlockLink;
*wBlockNum = 0;
WAITFOR(m_hDataLock);
pBlockLink = (DATA_AREA_LINK *)m_pBlockList->GetAddress();
__try
{
if (m_dwHoles != 0)
{
// find an unused block in the list. Either free and will fit, or never used
while (!((pBlockLink->bInUse == BLOCK_FREE) &&
((wByteSize <= pBlockLink->wBlockSize) ||
(pBlockLink->wBlockSize == 0))))
{
// get next block number and keep track of number
pBlockLink++;
(*wBlockNum)++;
}
// used a hole if this was previously used
if (pBlockLink->wBlockSize != 0)
m_dwHoles--;
}
else
{
// go right to the end
*wBlockNum = (WORD)m_pBlockList->GetElements();
pBlockLink += *wBlockNum;
}
// need pointer to previous block to update this one
pPrevBlockLink = pBlockLink;
// make sure this isn't the first one
if (pBlockLink != m_pBlockList->GetAddress())
pPrevBlockLink--;
// now we have one, record the information
pBlockLink->bInUse = BLOCK_INUSE;
pBlockLink->wBlockSize = wByteSize;
// mvs122899 - We need to initialize the internal addresses
// else if this is a block which is being reused we could end
// up with the wrong internal addresses
pBlockLink->lInternalAddress1 = 0;
pBlockLink->lInternalAddress2 = 0;
pBlockLink->wBytesInUse = 0;
pBlockLink->wDataStatus = 0;
pBlockLink->bNIOAccess = FALSE;
pBlockLink->dwDataBlockHandle = dwDataBlockHandle;
// store the offset to this block
if (pPrevBlockLink != pBlockLink)
pBlockLink->dwBlockOffset = pPrevBlockLink->dwBlockOffset + pPrevBlockLink->wBlockSize;
}
__except(MemoryExcFilter(GetExceptionInformation(),BLOCK_LIST))
{
dwStatus = GetExceptionCode();
switch (dwStatus)
{
case EXCEPTION_GMMF_DISKFULL: dwStatus = MEM_DISKFULL; break;
case EXCEPTION_GMMF_CORRUPTEDRGN: dwStatus = MEM_CORRUPT; break;
case EXCEPTION_GMMF_WRITEPAST: dwStatus = MEM_WRITEPAST; break;
default: dwStatus = MEM_UNKNOWN; break;
}
LETGO(m_hDataLock);
return(dwStatus);
}
__try
{
// point to the data area and clear it
char *pDataArea = (char *)m_pDataArea->GetAddress();
pDataArea += pBlockLink->dwBlockOffset;
memset(pDataArea, 0, pBlockLink->wBlockSize);
}
__except(MemoryExcFilter(GetExceptionInformation(),DATA_AREA))
{
dwStatus = GetExceptionCode();
switch (dwStatus)
{
case EXCEPTION_GMMF_DISKFULL: dwStatus = MEM_DISKFULL; break;
case EXCEPTION_GMMF_CORRUPTEDRGN: dwStatus = MEM_CORRUPT; break;
case EXCEPTION_GMMF_WRITEPAST: dwStatus = MEM_WRITEPAST; break;
default: dwStatus = MEM_UNKNOWN; break;
}
LETGO(m_hDataLock);
return(dwStatus);
}
// keep track of how many data blocks are currently in use
m_pBlockList->IncElements();
LETGO(m_hDataLock);
return(ERROR_SUCCESS);
}
//----(Member Function)-------------------------------------------------------
//
// @mfunc This function Sets the actual number of bytes in use
// for a datablock
//
// @parm IN WORD | wBlockNumber | Number of block
// @parm IN WORD | wNumBytes | Number of bytes in use
//
// @rvalue ERROR_SUCCESS | If successful
//
// @rvalue ERROR_INVALID_BLOCK | If block not in use
//
EXPORT32 DWORD CCommonMemory::SetBytesInUse(IN WORD wBlockNumber, IN WORD wNumBytes)
{
// get a pointer to the list of blocks
DATA_AREA_LINK *pBlockLink;// = (DATA_AREA_LINK *)m_pBlockList->GetAddress();
DWORD dwStatus = ERROR_SUCCESS;
WAITFOR(m_hDataLock);
pBlockLink = (DATA_AREA_LINK *)m_pBlockList->GetAddress();
__try
{
// jump to the requested block
pBlockLink += wBlockNumber;
if (pBlockLink->bInUse == BLOCK_FREE)
{
dwStatus = ERROR_INVALID_BLOCK;
}
else
{
// Set the data
__try
{
pBlockLink->wBytesInUse = wNumBytes;
}
__except(MemoryExcFilter(GetExceptionInformation(),DATA_AREA))
{
dwStatus = GetExceptionCode();
switch (dwStatus)
{
case EXCEPTION_GMMF_DISKFULL: dwStatus = MEM_DISKFULL; break;
case EXCEPTION_GMMF_CORRUPTEDRGN: dwStatus = MEM_CORRUPT; break;
case EXCEPTION_GMMF_WRITEPAST: dwStatus = MEM_WRITEPAST; break;
default: dwStatus = MEM_UNKNOWN; break;
}
LETGO(m_hDataLock);
return(dwStatus);
}
}
}
__except(MemoryExcFilter(GetExceptionInformation(),BLOCK_LIST))
{
dwStatus = GetExceptionCode();
switch (dwStatus)
{
case EXCEPTION_GMMF_DISKFULL: dwStatus = MEM_DISKFULL; break;
case EXCEPTION_GMMF_CORRUPTEDRGN: dwStatus = MEM_CORRUPT; break;
case EXCEPTION_GMMF_WRITEPAST: dwStatus = MEM_WRITEPAST; break;
default: dwStatus = MEM_UNKNOWN; break;
}
LETGO(m_hDataLock);
return(dwStatus);
}
LETGO(m_hDataLock);
return(dwStatus);
}
//----(Member Function)-------------------------------------------------------
//
// @mfunc This function deletes a block for storing real time data
//
// @parm IN WORD | wBlockNumber | Number of block to free
//
// @rvalue ERROR_SUCCESS | If successful
//
// @rvalue ERROR_INVALID_BLOCK | If block not in use
//
EXPORT32 DWORD CCommonMemory::DestroyDataBlock(IN WORD wBlockNumber)
{
// get a pointer to the list of blocks
DATA_AREA_LINK *pBlockLink;// = (DATA_AREA_LINK *)m_pBlockList->GetAddress();
DWORD dwStatus = ERROR_SUCCESS;
WAITFOR(m_hDataLock);
pBlockLink = (DATA_AREA_LINK *)m_pBlockList->GetAddress();
__try
{
// jump to the requested block
pBlockLink += wBlockNumber;
if (pBlockLink->bInUse == BLOCK_INUSE)
{
pBlockLink->bInUse = BLOCK_FREE;
m_dwHoles++; // made a hole
// keep track of how many data blocks are currently in use
m_pBlockList->DecElements();
}
else
{
dwStatus = ERROR_INVALID_BLOCK;
}
}
__except(MemoryExcFilter(GetExceptionInformation(),BLOCK_LIST))
{
dwStatus = GetExceptionCode();
switch (dwStatus)
{
case EXCEPTION_GMMF_DISKFULL: dwStatus = MEM_DISKFULL; break;
case EXCEPTION_GMMF_CORRUPTEDRGN: dwStatus = MEM_CORRUPT; break;
case EXCEPTION_GMMF_WRITEPAST: dwStatus = MEM_WRITEPAST; break;
default: dwStatus = MEM_UNKNOWN; break;
}
LETGO(m_hDataLock);
return(dwStatus);
}
LETGO(m_hDataLock);
return(dwStatus);
}
//----(Member Function)-------------------------------------------------------
//
// @mfunc This function returns a block of real time data
//
// @parm IN WORD | wBlockNumber | Number of block to access
//
// @parm IN WORD | wNumBytes | Number of bytes to return
//
// @parm OUT LPVOID | pData | Buffer to hold data
//
// @parm IN OPTIONAL WORD | wOffset | Number of bytes to offset from start
//
// @parm IN OPTIONAL BOOL | bIgnoreBytesInUse | Ignore bytes in use value and get block anyway
//
// @rvalue ERROR_SUCCESS | If successful
//
// @rvalue ERROR_INVALID_BLOCK | If block not in use
//
// @rvalue ERROR_INVALID_BLOCK_LENGTH | if wNumBytes is greater than block size
//
EXPORT32 DWORD CCommonMemory::GetDataBlock(IN WORD wBlockNumber,
IN WORD wNumBytes,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -