/*++ Copyright (c) 1997 Microsoft Corporation All rights reserved. Module Name: sharedat.cxx Abstract: Shared data implementation. Author: Albert Ting (AlbertT) 5-Oct-1997 Revision History: --*/ #include "spllibp.hxx" #pragma hdrstop #include "sharedat.hxx" LPCTSTR szSuffixFile = SZ_SUFFIX_FILE; /******************************************************************** TShareData::TBase Base functionality common to both TReadWrite and TRead. ********************************************************************/ TShareData:: TBase:: TBase( VOID ) : m_hMap( NULL ), m_pData( NULL ) { } VOID TShareData:: TBase:: vCleanup( VOID ) { if( m_pData ) { UnmapViewOfFile( m_pData ); m_pData = NULL; } if( m_hMap ) { CloseHandle( m_hMap ); m_hMap = NULL; } } TShareData:: TBase:: ~TBase( VOID ) { vCleanup(); } BOOL TShareData:: TBase:: bGetFullName( LPCTSTR pszName, LPTSTR pszFullName ) { UINT cchName; // // Validate input and determine the size of the name. // if( !pszName || !pszName[0] || ( cchName = lstrlen( pszName )) >= MAX_PATH ) { SetLastError( ERROR_INVALID_NAME ); return FALSE; } // // Create shared file object. // lstrcpy( pszFullName, pszName ); lstrcpy( &pszFullName[cchName], szSuffixFile ); return TRUE; } /******************************************************************** TShareData::TReadWrite Class that allows user to read and write a shared data object. Since there is only one valid writer, the vWriteBegin and vWriteEnd functions are rolled up together here. ********************************************************************/ TShareData:: TReadWrite:: TReadWrite( IN LPCTSTR pszName, IN DWORD cbSize, IN PSECURITY_ATTRIBUTES pSA ) : TBase() /*++ Routine Description: Create a shared data access object. Arguments: pszName - Name of shared memory object. pSA - Security attributes. Return Value: --*/ { TCHAR szFullName[kNameBufferMax]; if( bGetFullName( pszName, szFullName )) { m_hMap = CreateFileMapping( INVALID_HANDLE_VALUE, pSA, PAGE_READWRITE, 0, sizeof( TData ) + cbSize, szFullName ); if( m_hMap ) { m_pData = (pTData)MapViewOfFile( m_hMap, FILE_MAP_WRITE, 0, 0, 0 ); m_pData->cbSize = cbSize; // // Put ourselves in an inconsistent state so that clients won't // read bad data. The callee must call vWriteFirst() after // the first initialization. // m_pData->lCount2 = m_pData->lCount1 + 1; } } // // m_pData is our valid check. If this variable is NULL // then the object wasn't created correctly. // } VOID TShareData:: TReadWrite:: vWriteFirst( VOID ) { m_pData->lCount1 = m_pData->lCount2 = 0; } VOID TShareData:: TReadWrite:: vWriteBegin( VOID ) { InterlockedIncrement( &m_pData->lCount2 ); } VOID TShareData:: TReadWrite:: vWriteEnd( VOID ) { InterlockedIncrement( &m_pData->lCount1 ); } /******************************************************************** TShareData::TRead Read-only class. Since there can be multiple readers, the reader instance is separated out into a TReadSync class. ********************************************************************/ TShareData:: TRead:: TRead( IN LPCTSTR pszName, IN DWORD cbSize ) : TBase() /*++ Routine Description: Create a shared data access object. Arguments: pszName - Name of shared memory object. Return Value: --*/ { TCHAR szFullName[kNameBufferMax]; if( bGetFullName( pszName, szFullName )) { m_hMap = OpenFileMapping( FILE_MAP_READ, FALSE, szFullName ); if( m_hMap ) { m_pData = (pTData)MapViewOfFile( m_hMap, FILE_MAP_READ, 0, 0, 0 ); if( m_pData ) { if( m_pData->cbSize < cbSize ) { vCleanup(); SetLastError( ERROR_INVALID_PARAMETER ); } } } } // // m_pData is our valid check. If this variable is NULL // then the object wasn't created correctly. // } /******************************************************************** TShareData::TReadSync Synchronizes a read instance from a TShareData::Read object. There can be multiple TReadSyncs running concurrently for a given TShareData::Read object. ********************************************************************/ TShareData:: TReadSync:: TReadSync( TRead& Read ) : m_Read( Read ) { } VOID TShareData:: TReadSync:: vReadBegin( VOID ) { m_lCount = m_Read.m_pData->lCount1; } BOOL TShareData:: TReadSync:: bReadEnd( VOID ) { return m_Read.m_pData->lCount2 == m_lCount; }