/*++ Copyright (c) 1996 Microsoft Corporation All rights reserved. Module Name: sharemem.cxx Abstract: Shared memory implementation. Author: Albert Ting (AlbertT) 17-Dec-1996 Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "sharemem.hxx" #ifdef COUNTOF #undef COUNTOF #endif #define COUNTOF(x) (sizeof(x)/sizeof(*x)) LPCTSTR szPrefixFile = TEXT( "_ShrMemF" ); LPCTSTR szPrefixMutex = TEXT( "_ShrMemM" ); TShareMem:: TShareMem( IN UINT uSize, IN LPCTSTR pszName, IN UINT uFlags, IN PSECURITY_ATTRIBUTES psa, OPTIONAL OUT PUINT puSizeDisposition OPTIONAL ) : m_hFile( NULL ), m_hMutex( NULL ), m_pvBase( NULL ), m_pvUserData( NULL ) /*++ Routine Description: Create a shared memory access object. Arguments: uSize - Size of the buffer requested. pszName - Name of shared memory object. uFlags - Options kCreate - Create a new file mapping. If the mapping already exists, it will be used (see puSizeDisposition). If not specified, an existing one will be opened. kReadWrite - Open with ReadWrite access. If not specified, Read only access is used. psa - Pointer to security attributes. Used only if kCreate specified. puSizeDisposition - If the object already exists, returns its size. If the object did not exist, returns zero. Return Value: --*/ { UINT cchName; // // Validate input and determine the size of the name. // if( !uSize || !pszName || !pszName[0] || ( cchName = lstrlen( pszName )) >= MAX_PATH ) { SetLastError( ERROR_INVALID_PARAMETER ); return; } DWORD dwAccess = ( uFlags & kReadWrite ) ? FILE_MAP_READ | FILE_MAP_WRITE : FILE_MAP_READ; // // Pre-initialize output variables. // UINT uSizeDispositionDiscard; if( !puSizeDisposition ) { puSizeDisposition = &uSizeDispositionDiscard; } *puSizeDisposition = 0; // // Create or shared mutex that will protect the data. Create // the new name. This needs to be created first to protect // against multiple people trying to create the file mapping // simultaneously. // TCHAR szFullName[MAX_PATH + max( COUNTOF( szPrefixFile ), COUNTOF( szPrefixMutex ))]; lstrcpy( szFullName, pszName ); lstrcpy( &szFullName[cchName], szPrefixMutex ); m_hMutex = CreateMutex( psa, FALSE, szFullName ); if( !m_hMutex ) { return; } { // // Acquire the mutex for use while we're grabbing the resource. // WaitForSingleObject( m_hMutex, INFINITE ); BOOL bFileExists = TRUE; // // Create the name of the mapped file. // lstrcpy( &szFullName[cchName], szPrefixFile ); // // Either open or create the map file handle. // if( uFlags & kCreate ) { // // Create a new map. // m_hFile = CreateFileMapping( INVALID_HANDLE_VALUE, psa, ( uFlags & kReadWrite ) ? PAGE_READWRITE : PAGE_READONLY, 0, uSize, szFullName ); // // See if it already exists. // if( GetLastError() != ERROR_ALREADY_EXISTS ) { bFileExists = FALSE; } } else { // // Open existing map. // m_hFile = OpenFileMapping( dwAccess, FALSE, szFullName ); } if( m_hFile ) { // // Map the file into our address space. // m_pvBase = MapViewOfFile( m_hFile, dwAccess, 0, 0, 0 ); if( m_pvBase ) { if( bFileExists ) { *puSizeDisposition = GetHeader().uSize; } else { GetHeader().uHeaderSize = sizeof( HEADER ); GetHeader().uSize = uSize; } m_pvUserData = reinterpret_cast( m_pvBase ) + GetHeader().uHeaderSize; } } ReleaseMutex( m_hMutex ); } // // m_pvUserData is our valid check. If this variable is NULL // then the object wasn't created correctly. // } TShareMem:: ~TShareMem( VOID ) { if( m_hMutex ) { CloseHandle( m_hMutex ); } if( m_pvBase ) { UnmapViewOfFile( m_pvBase ); } if( m_hFile ) { CloseHandle( m_hFile ); } }