Click here to Skip to main content
15,885,920 members
Articles / Desktop Programming / MFC

Shared memory

Rate me:
Please Sign up or sign in to vote.
4.80/5 (6 votes)
28 Sep 20028 min read 221.5K   6K   84  
Share variables in the shared memory across processes
/********************************************************************************************
* MOD-NAME      : SharedMemory.cpp
* LONG-NAME     : 
*
* AUTHOR        : Martin Ziacek
* DEPARTMENT    : 
* TELEPHONE     : 
* CREATION-DATE : 09/05/2001 18:00:00
* SP-NO         : 
* FUNCTION      : 
* 
*********************************************************************************************/

#include "stdafx.h"
#include "helpers.h"
#include "SharedMemory.h"

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

/////////////////////////////////////////////////////////////////////////////
// CSharedMemory

IMPLEMENT_DYNAMIC(CSharedMemory, CObject)


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetLastError
 * DESCRIPTION          : 
 * RETURN TYPE          : void 
 * ARGUMENT             : DWORD dwErrCode
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:17:44
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
void CSharedMemory::SetLastError(DWORD dwErrCode)			//this method and following macro will
{															//provide trace output of error description
	m_dwLastError = dwErrCode;								//with file name and line number where
	::SetLastError(dwErrCode);								//error occures - it works correctly
}															//only in this order

#ifdef _DEBUG
#define SetLastError(err) DumpErrorCode(err,__LINE__,__FILE__); SetLastError(err)
#endif


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::CSharedMemory
 * DESCRIPTION          : 
 * RETURN TYPE          : 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwSize
 * ARGUMENT             : PINITMEMORY InitMemoryProcedure
 * ARGUMENT             : LPSECURITY_ATTRIBUTES lpsaAttributes
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:17:49
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
CSharedMemory::CSharedMemory(const TCHAR *szName, DWORD dwSize, PINITMEMORY InitMemoryProcedure,LPSECURITY_ATTRIBUTES lpsaAttributes )
	:	m_dwLastError(0),
		m_pNewAcl(NULL),
		m_pLogSid(NULL),
		m_pSysSid(NULL),
		m_pEvrSid(NULL),
		m_bCreated(FALSE),
		m_bFirst(TRUE),
		m_pSync(NULL),
		m_pLock(NULL),
		m_bSecPres(FALSE)
{
	do {
		OSVERSIONINFO osvi;
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		if (GetVersionEx(&osvi)) {

			TRACE(_T("osvi.dwMajorVersion = %d\n"),osvi.dwMajorVersion);
			TRACE(_T("osvi.dwMinorVersion = %d\n"),osvi.dwMinorVersion);

			if (osvi.dwMajorVersion >= 3) {
				if ((osvi.dwMinorVersion == 51) ||
					(osvi.dwMinorVersion == 0) ||
					(osvi.dwMinorVersion == 1)) {
					m_bSecPres = TRUE;
				}
			}
		} else {
			SetLastError(::GetLastError());
			break;
		}

		//copy or create security descriptor for objects
		if (m_bSecPres) {
			if (lpsaAttributes) {
				if (!SetSa(lpsaAttributes)) {
					break;
				}
			} else {
				if (!CreateSa()) {
					break;
				}
			}
		}

		//create synchronization mechanism
		m_pSync = new CSemaphore(1,1,CString(szName)+CString(_T("_Sync")),m_bSecPres ? &m_SecAtr : NULL);
		if (!m_pSync) {
			break;
		}
		m_pLock = new CSingleLock(m_pSync);
		if (!m_pLock) {
			break;
		}
		m_pLock->Lock();			//lock access

		// atempt to create file mapping in th page file ...
		m_hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE,m_bSecPres ? &m_SecAtr : NULL,PAGE_READWRITE,0,dwSize,szName);

		// ... it can already exist (it is not error) ...
		if (::GetLastError() == ERROR_ALREADY_EXISTS) {
			m_bFirst = FALSE;		//remember, we are not first
		}

		// ... it can fail ...
		if (m_hFileMap == NULL) {
			SetLastError(::GetLastError());
			break;
		}

		// ... but if it did not, map a view
		m_lpView = (LPBYTE) MapViewOfFile(m_hFileMap,FILE_MAP_READ | FILE_MAP_WRITE,0,0,0);

		if (!m_lpView) {
			SetLastError(::GetLastError());
			break;
		}

		//allow usage only of already existing size, could be less then requested
		if (m_bFirst) {
			::ZeroMemory(m_lpView,dwSize);
			m_dwMemSize = dwSize;
			CopyMemory(m_lpView+sizeof(DWORD),&m_dwMemSize,sizeof(DWORD));
		} else {
			CopyMemory(&m_dwMemSize,m_lpView+sizeof(DWORD),sizeof(DWORD));
		}

		//if everything is OK up to now, the we have shared memory
		m_bCreated = TRUE;
		m_CsName = szName;

		//and it can be initialized in one place
		if (InitMemoryProcedure) {
			m_pLock->Unlock();			//temporary unlock to allow access from InitMemoryProcedure()
			InitMemoryProcedure(this);
			m_pLock->Lock();
		}

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();	
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::~CSharedMemory
 * DESCRIPTION          : 
 * RETURN TYPE          : 
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:17:55
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
CSharedMemory::~CSharedMemory()
{
	if (m_lpView) UnmapViewOfFile(m_lpView);
	if (m_hFileMap) CloseHandle(m_hFileMap);
	if (m_pNewAcl) HeapFree(GetProcessHeap(), 0, m_pNewAcl);
	if (m_pLogSid) FreeSid(m_pLogSid);
	if (m_pSysSid) FreeSid(m_pSysSid);
	if (m_pEvrSid) FreeSid(m_pEvrSid);
	if (m_pLock) delete m_pLock;
	if (m_pSync) delete m_pSync;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetMemName
 * DESCRIPTION          : 
 * RETURN TYPE          : CString 
 * ARGUMENT             : void
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:17:58
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
CString CSharedMemory::GetMemName(void)
{
	if (m_bCreated) {
		return m_CsName;
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
		return CString(_T(""));
	}
}

#ifdef _DEBUG

/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::AssertValid
 * DESCRIPTION          : 
 * RETURN TYPE          : void 
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:02
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
void CSharedMemory::AssertValid()
{
	CObject::AssertValid();
	ASSERT(m_bCreated);
	ASSERT(m_hFileMap != NULL);
	ASSERT(m_hFileMap != INVALID_HANDLE_VALUE);
	ASSERT(m_lpView != NULL);
	ASSERT(m_pSync != NULL);
	ASSERT(m_pLock != NULL);
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::Dump
 * DESCRIPTION          : 
 * RETURN TYPE          : void 
 * ARGUMENT             : CDumpContext & dc
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:07
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
void CSharedMemory::Dump(CDumpContext & dc)
{
	CObject::Dump(dc);										//dump memory content, be carefull,
	DUMP((TCHAR *)LPCTSTR(m_CsName),m_lpView,m_dwMemSize);	//this could take a longer time
}
#endif


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetLastError
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:11
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::GetLastError()
{
	return m_dwLastError;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetMemSize
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:15
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::GetMemSize()
{
	if (m_bCreated) {
		return m_dwMemSize;
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
		return 0;
	}
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::AmIFirst
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : void
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:18
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::AmIFirst(void)
{
	return m_bFirst;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetSdMem
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : SECURITY_INFORMATION SecurityInformation
 * ARGUMENT             : PSECURITY_DESCRIPTOR SecurityDescriptor
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:22
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::SetSdMem(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor)
{
	BOOL rc = FALSE;

	if (m_bCreated) {

		rc = ::SetKernelObjectSecurity(m_hFileMap,SecurityInformation,SecurityDescriptor);

		if (!rc) {
			SetLastError(::GetLastError());
		}
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetSdMem
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : SECURITY_INFORMATION RequestedInformation
 * ARGUMENT             : PSECURITY_DESCRIPTOR pSecurityDescriptor
 * ARGUMENT             : DWORD nLength
 * ARGUMENT             : LPDWORD lpnLengthNeeded
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:27
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::GetSdMem(SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded)
{
	BOOL rc = FALSE;

	if (m_bCreated) {

		rc = ::GetKernelObjectSecurity(m_hFileMap,RequestedInformation,pSecurityDescriptor,nLength,lpnLengthNeeded);

		if (!rc) {
			SetLastError(::GetLastError());
		}
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetSdSem
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : SECURITY_INFORMATION SecurityInformation
 * ARGUMENT             : PSECURITY_DESCRIPTOR SecurityDescriptor
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:31
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::SetSdSem(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor)
{
	BOOL rc = FALSE;

	if (m_bCreated) {

		rc = ::SetKernelObjectSecurity(HANDLE(*m_pSync),SecurityInformation,SecurityDescriptor);

		if (!rc) {
			SetLastError(::GetLastError());
		}
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetSdSem
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : SECURITY_INFORMATION RequestedInformation
 * ARGUMENT             : PSECURITY_DESCRIPTOR pSecurityDescriptor
 * ARGUMENT             : DWORD nLength
 * ARGUMENT             : LPDWORD lpnLengthNeeded
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:35
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::GetSdSem(SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded)
{
	BOOL rc = FALSE;

	if (m_bCreated) {

		rc = ::GetKernelObjectSecurity(HANDLE(*m_pSync),RequestedInformation,pSecurityDescriptor,nLength,lpnLengthNeeded);

		if (!rc) {
			SetLastError(::GetLastError());
		}
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::CreateSa
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:39
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::CreateSa()
{
	BOOL rc = FALSE;

	SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;

	DWORD cbAcl;

	PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)m_SdEvent;

	do {
		// allow access to user logged on interactivelly
		if (!AllocateAndInitializeSid(&sidAuth,1,SECURITY_INTERACTIVE_RID,0,0,0,0,0,0,0,(void **)&m_pLogSid)) {
			SetLastError(::GetLastError());
			break;
		}
		// allow access to system
		if (!AllocateAndInitializeSid(&sidAuth,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,(void **)&m_pSysSid)) {
			SetLastError(::GetLastError());
			break;
		}
		// allow access to services
		if (!AllocateAndInitializeSid(&sidAuth,1,SECURITY_SERVICE_RID,0,0,0,0,0,0,0,(void **)&m_pEvrSid)) {
			SetLastError(::GetLastError());
			break;
		}

		cbAcl = GetLengthSid (m_pLogSid) + GetLengthSid (m_pSysSid) + GetLengthSid (m_pEvrSid) + 
				sizeof(ACL) + (3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
		m_pNewAcl = (PACL) HeapAlloc(GetProcessHeap(), 0, cbAcl);

		if (!m_pNewAcl) {
			SetLastError(::GetLastError());
			break;
		}

		if (!InitializeAcl(m_pNewAcl, cbAcl, ACL_REVISION)) {
			SetLastError(::GetLastError());
			break;
		}
		// allow everything to interractive user, system and services
		if (!AddAccessAllowedAce(	m_pNewAcl,
									ACL_REVISION,
									STANDARD_RIGHTS_ALL | 
									SPECIFIC_RIGHTS_ALL | 
									EVENT_ALL_ACCESS,
									m_pLogSid)) {
			SetLastError(::GetLastError());
			break;
		}
		if (!AddAccessAllowedAce(	m_pNewAcl,
									ACL_REVISION,
									STANDARD_RIGHTS_ALL | 
									SPECIFIC_RIGHTS_ALL | 
									EVENT_ALL_ACCESS,
									m_pSysSid)) {
			SetLastError(::GetLastError());
			break;
		}
		if (!AddAccessAllowedAce(	m_pNewAcl,
									ACL_REVISION,
									STANDARD_RIGHTS_ALL | 
									SPECIFIC_RIGHTS_ALL | 
									EVENT_ALL_ACCESS,
									m_pEvrSid)) {
			SetLastError(::GetLastError());
			break;
		}

		if (!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION)) {
			SetLastError(::GetLastError());
			break;
		}

		if (!SetSecurityDescriptorDacl(psdNewSD,TRUE,m_pNewAcl,FALSE)) {
			SetLastError(::GetLastError());
			break;
		}

		m_SecAtr.nLength = sizeof(m_SecAtr);
		m_SecAtr.lpSecurityDescriptor = psdNewSD;
		m_SecAtr.bInheritHandle = TRUE;

		rc = TRUE;

	} while (FALSE);

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetSa
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : LPSECURITY_ATTRIBUTES lpsaAttributes
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:18:48
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::SetSa(LPSECURITY_ATTRIBUTES lpsaAttributes)
{
	BOOL rc = FALSE;

	if (IsValidSecurityDescriptor(lpsaAttributes->lpSecurityDescriptor)) {

		m_SecAtr.bInheritHandle = lpsaAttributes->bInheritHandle;
		m_SecAtr.nLength = lpsaAttributes->nLength;

		m_SecAtr.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)m_SdEvent;
		ZeroMemory(m_SecAtr.lpSecurityDescriptor,sizeof(m_SdEvent));

		InitializeSecurityDescriptor(m_SecAtr.lpSecurityDescriptor,SECURITY_DESCRIPTOR_REVISION);

		SID *pOwner;
		BOOL bOwnerDefaulted;

		GetSecurityDescriptorOwner(
			((SECURITY_DESCRIPTOR *)(lpsaAttributes->lpSecurityDescriptor)),
			(void**)&pOwner,
			&bOwnerDefaulted);

		SetSecurityDescriptorOwner(
			((SECURITY_DESCRIPTOR *)(m_SecAtr.lpSecurityDescriptor)),
			pOwner,
			bOwnerDefaulted);

		SID *pGroup;
		BOOL bGroupDefaulted;

		GetSecurityDescriptorGroup(
			((SECURITY_DESCRIPTOR *)(lpsaAttributes->lpSecurityDescriptor)),
			(void**)&pGroup,
			&bGroupDefaulted);

		SetSecurityDescriptorGroup(
			((SECURITY_DESCRIPTOR *)(m_SecAtr.lpSecurityDescriptor)),
			pGroup,
			bGroupDefaulted);

		BOOL bPresent = FALSE;
		ACL *pSacl;
		BOOL bSaclDefaulted;

		GetSecurityDescriptorSacl(
			((SECURITY_DESCRIPTOR *)(lpsaAttributes->lpSecurityDescriptor)),
			&bPresent,
			&pSacl,
			&bSaclDefaulted);

		SetSecurityDescriptorSacl(
			((SECURITY_DESCRIPTOR *)(m_SecAtr.lpSecurityDescriptor)),
			bPresent,
			pSacl,
			bSaclDefaulted);

		bPresent = FALSE;
		ACL *pDacl;
		BOOL bDaclDefaulted;

		GetSecurityDescriptorDacl(
			((SECURITY_DESCRIPTOR *)(lpsaAttributes->lpSecurityDescriptor)),
			&bPresent,
			&pDacl,
			&bDaclDefaulted);

		SetSecurityDescriptorDacl(
			((SECURITY_DESCRIPTOR *)(m_SecAtr.lpSecurityDescriptor)),
			bPresent,
			pDacl,
			bDaclDefaulted);

		rc = TRUE;

	} else {
		SetLastError(ERROR_INVALID_PARAMETER);
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::AddValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD size
 * AUTHOR               : Martin Ziacek, Angela Aremu
 * DATE OF LAST UPDATE  : 24/09/2002 10:53:00
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::AddValue(const TCHAR *szName, DWORD size, void *pDefaultData)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		if (size == 0) {
			SetLastError(ERROR_BAD_LENGTH);
			break;
		}

		if (_tcsclen(szName)+1 > VAR_NAME_LENGTH) {
			SetLastError(RPC_S_STRING_TOO_LONG);
			break;
		}

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		DWORD dwCurrentUssage = 2*sizeof(DWORD);
		DWORD dwCount;
		DWORD dwNewCount;
		BOOL bExist = FALSE;

		CopyMemory(&dwCount,m_lpView,sizeof(DWORD));
		dwNewCount = dwCount + 1;

		LPBYTE pData = m_lpView;
		pData += 2*sizeof(DWORD);
		ValueHeader *pTmp = NULL;

		if (dwCount == 0) {		// zeroize memory, if this is first variable in the memory
			ZeroMemory(pData,m_dwMemSize-(2*sizeof(DWORD)));
		}

		//find index and count current memory usage
		for (DWORD i = 0; i < dwCount; i++) {
			pTmp = (ValueHeader *)pData;
			dwCurrentUssage += sizeof(ValueHeader);
			dwCurrentUssage += pTmp->dwLength;
			pData += sizeof(ValueHeader);
			pData += pTmp->dwLength;

			if (wcscmp(pTmp->wszValueName,wszName) == 0) {
				bExist = TRUE;
				break;
			}
		}

		if (bExist) {
			SetLastError(ERROR_ALREADY_EXISTS);
			break;
		}

		if ((dwCurrentUssage + sizeof(ValueHeader) + size) > m_dwMemSize) {
			SetLastError(ERROR_OUTOFMEMORY);
			break;
		}

		CopyMemory(m_lpView,&dwNewCount,sizeof(DWORD));

		ValueHeader newVal;
		ZeroMemory(&newVal,sizeof(ValueHeader));

		wcscpy(newVal.wszValueName,wszName);
		newVal.dwLength = size;

		CopyMemory(pData,&newVal,sizeof(ValueHeader));

		if (pDefaultData) {
			CopyMemory(pData+sizeof(ValueHeader),pDefaultData,size);
		}

		CEvent event_m(FALSE,TRUE,m_CsName+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event_m.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

//	ASSERT(rc);

	return rc;
}

/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::AddDwordValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwDefault
 * AUTHOR               : Angela Aremu
 * DATE OF LAST UPDATE  : 24/09/2002 10:53:00
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::AddDwordValue(const TCHAR *szName, DWORD dwDefault)
{
	return AddValue(szName,sizeof(DWORD),&dwDefault);
}

/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::DeleteValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:00
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::DeleteValue(const TCHAR *szName)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif
		DWORD dwCount;
		BOOL bFound = FALSE;

		CopyMemory(&dwCount,m_lpView,sizeof(DWORD));

		LPBYTE pData = m_lpView;
		pData += 2*sizeof(DWORD);
		ValueHeader *pTmp = NULL;

		DWORD dwLengthToZero = 0;
		DWORD dwMoveLength = 0;
		DWORD dwNewCount = dwCount - 1;

		DWORD dwDeleted = 0;

		BYTE *memToZero = NULL;
		BYTE *moveFrom = NULL;
		BYTE *moveTo = NULL;

		for (DWORD i = 0; i < dwCount; i++) {

			pTmp = (ValueHeader *)pData;
			pData += sizeof(ValueHeader);
			pData += pTmp->dwLength;

			dwMoveLength += sizeof(ValueHeader);
			dwMoveLength += pTmp->dwLength;

			if (wcscmp(pTmp->wszValueName,wszName) == 0) {
				bFound = TRUE;
				moveFrom = pData;
				moveTo = pData - (pTmp->dwLength + sizeof(ValueHeader));

				dwMoveLength = sizeof(ValueHeader);
				dwMoveLength += pTmp->dwLength;

				dwDeleted = dwMoveLength;

				dwLengthToZero = sizeof(ValueHeader);
				dwLengthToZero += pTmp->dwLength;
			}
		}

		if (!bFound) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		memToZero = pData - dwDeleted;

		MoveMemory(moveTo,moveFrom,dwMoveLength);
		CopyMemory(m_lpView,&dwNewCount,sizeof(DWORD));
		ZeroMemory(memToZero,dwLengthToZero);

		CEvent event_m(FALSE,TRUE,m_CsName+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event_m.SetEvent();

		CEvent event(FALSE,TRUE,CString(szName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetVariablesCount
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * ARGUMENT             : void
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:05
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::GetVariablesCount(void)
{
	DWORD dwCount = 0;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();
		CopyMemory(&dwCount,m_lpView,sizeof(DWORD));
		m_pLock->Unlock();

		m_dwLastError = 0;

	} while (FALSE);

	return dwCount;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetValueInfo
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : DWORD dwIndex
 * ARGUMENT             : ValueHeader *pVarInfo
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:09
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::GetValueInfo(DWORD dwIndex, ValueHeader *pVarInfo)
{
	BOOL rc = FALSE;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}

		DWORD dwCount;

		m_pLock->Lock();

		CopyMemory(&dwCount,m_lpView,sizeof(DWORD));

		LPBYTE pData = m_lpView;
		pData += 2*sizeof(DWORD);
		ValueHeader *pTmp = NULL;

		if (dwIndex >= dwCount) {
			SetLastError(ERROR_NOT_FOUND);
			break;
		}

		for (DWORD i = 0; i < dwIndex; i++) {
			pTmp = (ValueHeader *)pData;
			pData += sizeof(ValueHeader);
			pData += pTmp->dwLength;
		}
		*pVarInfo = *((ValueHeader *)pData);

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::FindValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const WCHAR *wszName
 * ARGUMENT             : LPBYTE *pData
 * ARGUMENT             : ValueHeader **pTmp
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:13
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::FindValue(const WCHAR *wszName,LPBYTE *pData, ValueHeader **pTmp)
{
	BOOL rc = FALSE;

	*pData += 2*sizeof(DWORD);

	DWORD dwCount;
	CopyMemory(&dwCount,m_lpView,sizeof(DWORD));

	*pData = m_lpView;
	*pData += 2*sizeof(DWORD);
	*pTmp = NULL;

	for (DWORD i = 0; i < dwCount; i++) {
		*pTmp = (ValueHeader *)*pData;
		*pData += sizeof(ValueHeader);
		*pData += (*pTmp)->dwLength;
		if (wcscmp((*pTmp)->wszValueName,wszName) == 0) {
			rc = TRUE;
			break;
		}
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : *CSharedMemory::AllocateUnicodeStr
 * DESCRIPTION          : 
 * RETURN TYPE          : WCHAR 
 * ARGUMENT             : const char *szStr
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:17
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
WCHAR *CSharedMemory::AllocateUnicodeStr(const char *szStr)
{
	WCHAR *wszStr = NULL;

	DWORD dwLn = strlen(szStr)+2;
	wszStr = new WCHAR[dwLn];
	if (!MultiByteToWideChar (CP_ACP, 0, szStr, -1, wszStr, dwLn)) {
		SetLastError(::GetLastError());
		if (wszStr) delete [] wszStr;
		wszStr = NULL;
	}

	return wszStr;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : void *bData
 * ARGUMENT             : DWORD dwLength
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:20
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::SetValue(const TCHAR *szName, void *bData, DWORD dwLength)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		if (dwLength == 0) {
			SetLastError(ERROR_BAD_LENGTH);
			break;
		}

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif
		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (dwLength > pTmp->dwLength) {
			SetLastError(ERROR_NOT_ENOUGH_MEMORY);
			break;
		}

		ZeroMemory(pData - pTmp->dwLength,pTmp->dwLength);
		CopyMemory(pData - pTmp->dwLength,bData,dwLength);

		CEvent event(FALSE,TRUE,CString(szName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : void *bData
 * ARGUMENT             : LPDWORD dwLength
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:24
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::GetValue(const TCHAR *szName, void *bData, LPDWORD dwLength)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (bData == NULL) {
			*dwLength = pTmp->dwLength;
			rc = TRUE;
			break;
		} 

		if (*dwLength < pTmp->dwLength) {
			*dwLength = pTmp->dwLength;
			SetLastError(ERROR_INSUFFICIENT_BUFFER);
			break;
		}

		*dwLength = pTmp->dwLength;
		CopyMemory(bData,pData - pTmp->dwLength,pTmp->dwLength);

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::SetDwordValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:29
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::SetDwordValue(const TCHAR *szName, DWORD dwVal)
{
	return SetValue(szName,&dwVal,sizeof(DWORD));
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::GetDwordValue
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwDefVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:33
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::GetDwordValue(const TCHAR *szName, DWORD dwDefVal)
{
	DWORD dwVal = 0;
	DWORD dwLn = sizeof(DWORD);
	DWORD rc = (DWORD)GetValue(szName,&dwVal,&dwLn);

	if (rc) {
		rc = dwVal;
	} else {
		rc = dwDefVal;
	}

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : *CSharedMemory::GetPointer
 * DESCRIPTION          : 
 * RETURN TYPE          : void 
 * ARGUMENT             : const TCHAR *szName
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:37
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
void *CSharedMemory::GetPointer(const TCHAR *szName)
{
	void *rc = NULL;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		rc = pData - pTmp->dwLength;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::ExistValue
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:45
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::ExistValue(const TCHAR *szName)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		m_pLock->Lock();
		rc = FindValue(wszName,&pData,&pTmp);
		m_pLock->Unlock();

		m_dwLastError = 0;

	} while (FALSE);

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::IsCreated
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : void
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:49
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::IsCreated(void)
{
	return m_bCreated;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::WaitForValueChange
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwMilliseconds
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:52
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::WaitForValueChange(const TCHAR *szName, DWORD dwMilliseconds)
{
	DWORD dwRet = WAIT_FAILED;

	if (ExistValue(szName)) {
		CEvent event(FALSE,TRUE,CString(szName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		dwRet = ::WaitForSingleObject(HANDLE(event),dwMilliseconds);
		if (dwRet == WAIT_FAILED) SetLastError(::GetLastError());
	} else {
		SetLastError(ERROR_FILE_NOT_FOUND);
	}

	return dwRet;
}

/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::WaitForMultipleValuesChanges
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : DWORD dwMilliseconds
 * AUTHOR               : Angela Aremu	
 * DATE OF LAST UPDATE  : 24/09/2002 10:53:00
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::WaitForMultipleValuesChanges(CStringArray & str,BOOL bWaitForAll , DWORD dwMilliseconds)
{
	DWORD dwRet = WAIT_FAILED;

	if (m_bCreated) {

		HANDLE *hEvHndl = new HANDLE[str.GetSize()];

		for (int i = 0; i < str.GetSize(); i++) {
			hEvHndl[i] = CreateEvent(m_bSecPres ? &m_SecAtr : NULL,FALSE,FALSE,str[i]+_T("_Event"));

			if (hEvHndl[i] == NULL) {
				SetLastError(::GetLastError());
				break;
			}
		}

		if (hEvHndl[i] != NULL) {

			dwRet = WaitForMultipleObjects(str.GetSize(),hEvHndl,bWaitForAll,dwMilliseconds);

			if (dwRet == WAIT_FAILED) {
				SetLastError(::GetLastError());
			}
		}

		for (i = 0; i < str.GetSize(); i++) {
			if (hEvHndl[i]) {
				CloseHandle(hEvHndl[i]);
			}
		}

		delete [] hEvHndl;

	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return dwRet;
}

/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::WaitForMemChange
 * DESCRIPTION          : 
 * RETURN TYPE          : DWORD 
 * ARGUMENT             : DWORD dwMilliseconds
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:19:56
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
DWORD CSharedMemory::WaitForMemChange(DWORD dwMilliseconds)
{
	DWORD dwRet = WAIT_FAILED;

	if (m_bCreated) {
		CEvent event(FALSE,TRUE,m_CsName+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		dwRet = ::WaitForSingleObject(HANDLE(event),dwMilliseconds);
		if (dwRet == WAIT_FAILED) SetLastError(::GetLastError());
	} else {
		SetLastError(ERROR_OBJECT_NOT_FOUND);
	}

	return dwRet;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedIncrement
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : LPLONG plNewVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:01
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedIncrement(const TCHAR *szName, LPLONG plNewVal)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

		LONG lValue;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (pTmp->dwLength != sizeof(LONG)) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		} 

		CopyMemory(&lValue,pData - pTmp->dwLength,pTmp->dwLength);
		lValue++;
		if (plNewVal) *plNewVal = lValue;
		CopyMemory(pData - pTmp->dwLength,&lValue,pTmp->dwLength);

		CEvent event(FALSE,TRUE,CString(szName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedDecrement
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szName
 * ARGUMENT             : LPLONG plNewVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:05
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedDecrement(const TCHAR *szName, LPLONG plNewVal)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

		LONG lValue;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (pTmp->dwLength != sizeof(LONG)) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&lValue,pData - pTmp->dwLength,pTmp->dwLength);
		lValue--;
		if (plNewVal) *plNewVal = lValue;
		CopyMemory(pData - pTmp->dwLength,&lValue,pTmp->dwLength);

		CEvent event(FALSE,TRUE,CString(szName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedExchange
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szTargetName
 * ARGUMENT             : LONG lNewVal
 * ARGUMENT             : LPLONG plPrevValue
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:10
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedExchange(const TCHAR *szTargetName, LONG lNewVal, LPLONG plPrevValue)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

		LONG lValue;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szTargetName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szTargetName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (pTmp->dwLength != sizeof(LONG)) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&lValue,pData - pTmp->dwLength,pTmp->dwLength);
		if (plPrevValue) *plPrevValue = lValue;
		CopyMemory(pData - pTmp->dwLength,&lNewVal,pTmp->dwLength);

		CEvent event(FALSE,TRUE,CString(szTargetName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedTestExchange
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szTargetName
 * ARGUMENT             : LONG lOldValue
 * ARGUMENT             : LONG lNewValue
 * ARGUMENT             : LPLONG plPrevValue
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:15
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedTestExchange(const TCHAR *szTargetName,LONG lOldValue,LONG lNewValue, LPLONG plPrevValue)
{
	return InterlockedCompareExchange(szTargetName,lNewValue,lOldValue,plPrevValue);
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedCompareExchange
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szTargetName
 * ARGUMENT             : LONG lExchange
 * ARGUMENT             : LONG lComperand
 * ARGUMENT             : LPLONG plIntiVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:19
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedCompareExchange(const TCHAR *szTargetName, LONG lExchange, LONG lComperand, LPLONG plIntiVal)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

		LONG lValue;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szTargetName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szTargetName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (pTmp->dwLength != sizeof(LONG)) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&lValue,pData - pTmp->dwLength,pTmp->dwLength);

		if (lValue == lComperand) {
			CopyMemory(pData - pTmp->dwLength,&lExchange,pTmp->dwLength);
		}

		if (plIntiVal) *plIntiVal = lValue;

		CEvent event(FALSE,TRUE,CString(szTargetName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::InterlockedExchangeAdd
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : const TCHAR *szTargetName
 * ARGUMENT             : LONG lIncrement
 * ARGUMENT             : LPLONG plIntiVal
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:24
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::InterlockedExchangeAdd(const TCHAR *szTargetName, LONG lIncrement, LPLONG plIntiVal)
{
	BOOL rc = FALSE;
	WCHAR *wszName = NULL;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		LPBYTE pData = NULL;
		ValueHeader *pTmp = NULL;

		LONG lValue;

#ifndef _UNICODE
		wszName = AllocateUnicodeStr(szTargetName);
		if (!wszName) {
			break;
		}
#else
		wszName = (WCHAR *)szTargetName;
#endif

		if (!FindValue(wszName,&pData,&pTmp)) {
			SetLastError(ERROR_FILE_NOT_FOUND);
			break;
		}

		if (pTmp->dwLength != sizeof(LONG)) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&lValue,pData - pTmp->dwLength,pTmp->dwLength);

		LONG lNew = lValue + lIncrement;
		CopyMemory(pData - pTmp->dwLength,&lNew,pTmp->dwLength);

		if (plIntiVal) *plIntiVal = lValue;

		CEvent event(FALSE,TRUE,CString(szTargetName)+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

#ifndef _UNICODE
	if (wszName) delete [] wszName;
#endif

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::Write
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : BYTE *pbData
 * ARGUMENT             : DWORD dwLength
 * ARGUMENT             : DWORD dwOffset
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:29
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::Write(BYTE *pbData, DWORD dwLength, DWORD dwOffset)
{
	BOOL rc = FALSE;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		DWORD dw;

		CopyMemory(&dw,m_lpView,sizeof(DWORD));

		//test - no variables
		if (dw != 0) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&dw,m_lpView+sizeof(DWORD),sizeof(DWORD));

		if ((dwLength + dwOffset) > (dw-2*sizeof(DWORD))) {
			SetLastError(ERROR_BAD_LENGTH);
			break;
		}

		CopyMemory(m_lpView+((2*sizeof(DWORD))+dwOffset),pbData,dwLength);

		//at the end set event
		CEvent event_m(FALSE,TRUE,m_CsName+CString(_T("_Event")),m_bSecPres ? &m_SecAtr : NULL);
		event_m.SetEvent();

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

	return rc;
}


/**************************************************************************************
 * PROG-NAME            : 
 * LONG-NAME            : 
 * FUNCTION             : CSharedMemory::Read
 * DESCRIPTION          : 
 * RETURN TYPE          : BOOL 
 * ARGUMENT             : BYTE *pbData
 * ARGUMENT             : DWORD dwLength
 * ARGUMENT             : DWORD dwOffset
 * AUTHOR               : Martin Ziacek
 * DATE OF LAST UPDATE  : 13/11/2001 10:20:33
 * GLOBAL READ          :
 * GLOBAL WRITE         :
 * FUNCTION CALLS       :
 * ERROR-EXITS          :
 * SIDE-EFFECTS         :
 **************************************************************************************/
BOOL CSharedMemory::Read(BYTE *pbData, DWORD dwLength, DWORD dwOffset)
{
	BOOL rc = FALSE;

	do {
		if (!m_bCreated) {
			SetLastError(ERROR_OBJECT_NOT_FOUND);
			break;
		}
		m_pLock->Lock();

		DWORD dw;

		CopyMemory(&dw,m_lpView,sizeof(DWORD));

		//test - no variables
		if (dw != 0) {
			SetLastError(ERROR_INVALID_DATA);
			break;
		}

		CopyMemory(&dw,m_lpView+sizeof(DWORD),sizeof(DWORD));

		if ((dwLength + dwOffset) > (dw-2*sizeof(DWORD))) {
			SetLastError(ERROR_BAD_LENGTH);
			break;
		}

		CopyMemory(pbData,m_lpView+((2*sizeof(DWORD))+dwOffset),dwLength);

		rc = TRUE;

	} while (FALSE);

	if (m_pLock) m_pLock->Unlock();

	return rc;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions