/* ------------------------------------------------------------------------ mapfile.cpp (was bbmpfile.cpp) A wrapper function to perform the cook book type operations required to map a file into memory. Maps the whole file, and nothing but the file, so help me God. Returns a pointer to void; NULL on error. An error also results in an entry in the event log, unless the error is "file not found" during CreateFile(). Copyright (C) 1994, 1995 Microsoft Corporation. All Rights Reserved. Author Lindsay Harris - lindsayh ------------------------------------------------------------------------ */ #include #include "mapfile.h" #ifndef _ASSERT #define _ASSERT( f ) if( (f) ) ; else DebugBreak() #endif /* ------------------------------------------------------------------------ CMapFile::CMapFile Constructor for unicode mapping. Author Lindsay Harris - lindsayh History 16:11 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version, to support tracking of objects in exception handling. ------------------------------------------------------------------------ */ CMapFile::CMapFile( const WCHAR *pwchFileName, BOOL fWriteEnable, BOOL fTrack ) { HANDLE hFile; // Ditto. // Set default values corresponding to no mapping happened. // m_pv = NULL; m_cb = 0; m_fFlags = 0; // Until later. hFile = CreateFileW( pwchFileName, fWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { // Only legitimate reason for coming here is non-existent file. // if ( GetLastError() != ERROR_FILE_NOT_FOUND && GetLastError() != ERROR_PATH_NOT_FOUND ) { // Error case // m_pv = NULL; } return; // Default values are failure. } wcsncpy( m_rgwchFileName, pwchFileName, MAX_PATH ); MapFromHandle( hFile, fWriteEnable, 0 ); BOOL fClose = CloseHandle( hFile ); _ASSERT( fClose ) ; return; } /* ------------------------------------------------------------------------ CMapFile::CMapFile Constructor for ascii file name version. Author Lindsay Harris - lindsayh History: 16:13 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version to handle tracking of objects for exception handling. ------------------------------------------------------------------------ */ CMapFile::CMapFile( const char *pchFileName, BOOL fWriteEnable, BOOL fTrack, DWORD cbIncrease ) { HANDLE hFile; // Ditto. // Set default values corresponding to no mapping happened. m_pv = NULL; m_cb = 0; m_fFlags = 0; // None set yet. hFile = CreateFile( pchFileName, fWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { // Only legitimate reason for coming here is non-existent file. // if ( GetLastError() != ERROR_FILE_NOT_FOUND && GetLastError() != ERROR_PATH_NOT_FOUND ) { // Error case // m_pv = NULL; } return; } MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pchFileName, -1, m_rgwchFileName, MAX_PATH ); MapFromHandle( hFile, fWriteEnable, cbIncrease ); BOOL fClose = CloseHandle( hFile ); _ASSERT( fClose ) ; return; } /* ------------------------------------------------------------------------ CMapFile::CMapFile. Constructor for ascii file name version. Note: Creates file handle if necessary. Does not close file handle. Author Lindsay Harris - lindsayh History: 16:13 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version to handle tracking of objects for exception handling. ------------------------------------------------------------------------ */ CMapFile::CMapFile( const char *pchFileName, HANDLE & hFile, BOOL fWriteEnable, DWORD cbIncrease ) { // Set default values corresponding to no mapping happened. // m_pv = NULL; m_cb = 0; m_fFlags = 0; // None set yet. if ( INVALID_HANDLE_VALUE == hFile ) { hFile = CreateFile( pchFileName, fWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { // Only legitimate reason for coming here is non-existent file. // if ( GetLastError() != ERROR_FILE_NOT_FOUND && GetLastError() != ERROR_PATH_NOT_FOUND ) { // Error case // m_pv = NULL; } return; } } MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pchFileName, -1, m_rgwchFileName, MAX_PATH ); MapFromHandle( hFile, fWriteEnable, cbIncrease ); return; } /* ------------------------------------------------------------------------ CMapFile::CMapFile Constructor when a file handle is available rather than a name. Note that it does not closes the handle Author Lindsay Harris - lindsayh History 16:14 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version to allow object tracking. Based on CarlK's function. ------------------------------------------------------------------------ */ CMapFile::CMapFile( HANDLE hFile, BOOL fWriteEnable, BOOL fTrack, DWORD cbIncrease ) { m_pv = NULL; m_cb = 0; // Set defaults. m_fFlags = 0; // None set yet. wcsncpy( m_rgwchFileName, L"", MAX_PATH ); MapFromHandle( hFile, fWriteEnable, cbIncrease ); return; } /* ------------------------------------------------------------------------ CMapFile::~CMapFile Destructor. Two purposes, being to unmap the file, and optionally remove it from the track data. Author Lindsay Harris - lindsayh History 16:22 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] Numero Uno. ------------------------------------------------------------------------ */ CMapFile::~CMapFile( void ) { // // Unmap the file, if we succeeded in mapping it first! // if ( !(m_fFlags & MF_RELINQUISH) ) { // We're still controlling this file, so stick with it. // if ( m_pv ) { UnmapViewOfFile( m_pv ); } } return; } /* ------------------------------------------------------------------------ CMapFile::MapFromHandle Does the real work of mapping. Given a handle to the file, go through the motions of mapping, and recording what happens. Reports errors as needed. Also adjusts file size if requested. Author Lindsay Harris - lindsayh Carl Kadie - carlk History 16:30 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version, based on older code with CarlK enhancements. ------------------------------------------------------------------------ */ void CMapFile::MapFromHandle( HANDLE hFile, BOOL fWriteEnable, DWORD cbIncrease ) { if ( !fWriteEnable && cbIncrease != 0 ) return; // This is non-sensical. m_cb = GetFileSize( hFile, NULL ); DWORD cbNewSize = 0; // // Determine if the file is to grow. Only pass a non-zero size // to the system if the size is growing - it's probably faster, and // the most likely common case. // if ( cbIncrease ) { cbNewSize = m_cb += cbIncrease; } else { if ( m_cb == 0 ) return; // Nothing there. } #if 1 if ( cbIncrease ) { _ASSERT(fWriteEnable); // // Make sure the file is the correct size. // DWORD fpos; BOOL fSetEnd; if ( (DWORD)-1 == ( fpos = SetFilePointer( hFile, cbNewSize, NULL, FILE_BEGIN )) || !(fSetEnd = SetEndOfFile( hFile )) ) { // // Error case // m_pv = NULL; return; } } #endif // // Create the mapping object. // HANDLE hFileMap; // Intermediate step. hFileMap = CreateFileMapping( hFile, NULL, fWriteEnable ? PAGE_READWRITE : PAGE_READONLY, 0, cbNewSize, NULL ); if ( !hFileMap ) { // Error case // m_pv = NULL; return; } // // Get the pointer mapped to the desired file. // m_pv = MapViewOfFile( hFileMap, fWriteEnable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0 ); if ( !m_pv ) { // Error case // m_pv = NULL; m_cb = 0; // Also set to zero, just in case. } // // Now that we have our pointer, we can close the mapping object. // BOOL fClose = CloseHandle( hFileMap ); _ASSERT( fClose ); return; } /* ------------------------------------------------------------------------- pvMapFile Map a file into memory and return the base address, NULL on failure. Author Lindsay Harris - lindsayh History 14:21 on Mon 20 Feb 1995 -by- Lindsay Harris [lindsayh] Amended to use unicode file name. 10:18 on Tue 29 Nov 1994 -by- Lindsay Harris [lindsayh] Made a separately compiled module. 10:55 on Mon 10 Oct 1994 -by- Lindsay Harris [lindsayh] Added FILE_FLAG_SEQUENTIAL_SCAN to speed up directory reading. 17:38 on Wed 06 Jul 1994 -by- Lindsay Harris [lindsayh] Make write enable code functional; clean up some old ideas. 15:35 on Wed 06 Apr 1994 -by- Lindsay Harris [lindsayh] Adding this comment, written some time back. ------------------------------------------------------------------------- */ void * pvMapFile( DWORD *pdwSize, const WCHAR *pwchFileName, BOOL bWriteEnable ) { // // Cook book formula. // VOID *pvRet; // Returned to caller HANDLE hFileMap; // Used during operations, closed before return HANDLE hFile; // Ditto. hFile = CreateFileW( pwchFileName, bWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { // Only legitimate reason for coming here is non-existent file. // if ( GetLastError() != ERROR_FILE_NOT_FOUND && GetLastError() != ERROR_PATH_NOT_FOUND ) { // Error case } return NULL; } // // If the caller wants to know the size (usually does) then get it now. // if ( pdwSize ) *pdwSize = GetFileSize( hFile, NULL ); // // Create the mapping object. // hFileMap = CreateFileMapping( hFile, NULL, bWriteEnable ? PAGE_READWRITE : PAGE_READONLY, 0, 0, NULL ); if ( !hFileMap ) { // Error case // BOOL fClose = CloseHandle( hFile ); // No handle leaks. _ASSERT( fClose ) ; return NULL; } // // Get the pointer mapped to the desired file. // pvRet = MapViewOfFile( hFileMap, bWriteEnable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0 ); if ( !pvRet ) { // Error case // } // // Now that we have our pointer, we can close the file and the // mapping object. // BOOL fClose = CloseHandle( hFileMap ); _ASSERT( fClose || hFileMap == 0 ) ; fClose = CloseHandle( hFile ); _ASSERT( fClose || hFile == INVALID_HANDLE_VALUE ) ; return pvRet; } /* ------------------------------------------------------------------------- pvMapFile Map a file into memory and return the base address, NULL on failure. Author Lindsay Harris - lindsayh History 10:18 on Tue 29 Nov 1994 -by- Lindsay Harris [lindsayh] Made a separately compiled module. 10:55 on Mon 10 Oct 1994 -by- Lindsay Harris [lindsayh] Added FILE_FLAG_SEQUENTIAL_SCAN to speed up directory reading. 17:38 on Wed 06 Jul 1994 -by- Lindsay Harris [lindsayh] Make write enable code functional; clean up some old ideas. 15:35 on Wed 06 Apr 1994 -by- Lindsay Harris [lindsayh] Adding this comment, written some time back. ------------------------------------------------------------------------- */ void * pvMapFile( DWORD *pdwSize, const char *pchFileName, BOOL bWriteEnable ) { // // Cook book formula. // VOID *pvRet; /* Returned to caller */ HANDLE hFileMap; // Used during operations, closed before return HANDLE hFile; // Ditto. hFile = CreateFile( pchFileName, bWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { // Only legitimate reason for coming here is non-existent file. // if ( GetLastError() != ERROR_FILE_NOT_FOUND && GetLastError() != ERROR_PATH_NOT_FOUND ) { // Error case // } return NULL; } // // If the caller wants to know the size (usually does) then get it now. // if ( pdwSize ) *pdwSize = GetFileSize( hFile, NULL ); // // Create the mapping object. // hFileMap = CreateFileMapping( hFile, NULL, bWriteEnable ? PAGE_READWRITE : PAGE_READONLY, 0, 0, NULL ); if ( !hFileMap ) { // Error case // BOOL fClose = CloseHandle( hFile ); // No handle leaks. _ASSERT( fClose ) ; return NULL; } // // Get the pointer mapped to the desired file. // pvRet = MapViewOfFile( hFileMap, bWriteEnable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0 ); if ( !pvRet ) { // Error case // } // // Now that we have our pointer, we can close the file and the // mapping object. // BOOL fClose = CloseHandle( hFileMap ); _ASSERT( fClose || hFileMap == 0 ) ; fClose = CloseHandle( hFile ); _ASSERT( fClose || hFile == INVALID_HANDLE_VALUE ) ; return pvRet; } /* ------------------------------------------------------------------------- pvFromHandle Creates a mapped file from an file handle. Does not close that handle. History 21 Dec 1994 -by- Carl Kadie [carlk] Based on pvMapFile code by Lindsay Harris [lindsayh] ------------------------------------------------------------------------- */ void * pvFromHandle( HANDLE hFile, BOOL bWriteEnable, // If the file is to be writeable DWORD * pdwSizeFinal, // If not Null, returns the final size of the file DWORD dwSizeIncrease ) // Use 0 if the size is not to increase { DWORD dwSize; VOID *pvRet; /* Returned to caller */ HANDLE hFileMap; dwSize = GetFileSize( hFile, NULL ) + dwSizeIncrease; if ( pdwSizeFinal ) { *pdwSizeFinal = dwSize; } // If the ultimate size of the file is 0, then return NULL. The // calling program may decide that this is OK. // if ( !dwSize) { return NULL; } #if 1 if ( dwSizeIncrease ) { _ASSERT(bWriteEnable); // // Make sure the file is the correct size. // DWORD fpos; BOOL fSetEnd; if ( (DWORD)-1 == (fpos = SetFilePointer( hFile, dwSize, NULL, FILE_BEGIN )) || !(fSetEnd = SetEndOfFile( hFile )) ) { // // Error case // BOOL fClose = CloseHandle( hFile ); // No handle leaks. return NULL; } } #endif // // Create the mapping object. // hFileMap = CreateFileMapping( hFile, NULL, bWriteEnable ? PAGE_READWRITE : PAGE_READONLY, 0, dwSize, NULL ); if ( !hFileMap ) { // Error case // BOOL fClose = CloseHandle( hFile ); // No handle leaks. return NULL; } // // Get the pointer mapped to the desired file. // pvRet = MapViewOfFile( hFileMap, bWriteEnable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0 ); if ( !pvRet ) { // Log the error, but continue, which returns the error. // #if 0 char rgchErr[ MAX_PATH + 32 ]; wsprintf( rgchErr, "MapViewOfFile" ); LogErrorEvent( MSG_GEN_FAIL, rgchErr, "pvFromHandle" ); #endif } // // Now that we have our pointer, we can close the file and the // mapping object. // BOOL fClose = CloseHandle( hFileMap ); _ASSERT( fClose ) ; return pvRet; } /* ------------------------------------------------------------------------- pvMapFile Map a file into memory and return the base address, NULL on failure. Also, allows the file to be grown. History 11:08 on Tue 18 Oct 1994 -by- Carl Kadie [carlk] Generalize pvMapFile to add support for adding to the file 10:55 on Mon 10 Oct 1994 -by- Lindsay Harris [lindsayh] Added FILE_FLAG_SEQUENTIAL_SCAN to speed up directory reading. 17:38 on Wed 06 Jul 1994 -by- Lindsay Harris [lindsayh] Make write enable code functional; clean up some old ideas. 15:35 on Wed 06 Apr 1994 -by- Lindsay Harris [lindsayh] Adding this comment, written some time back. ------------------------------------------------------------------------- */ void * pvMapFile( const char * pchFileName, // The name of the file BOOL bWriteEnable, // If the file is to be writeable DWORD * pdwSizeFinal, // If not Null, returns the final size of the file DWORD dwSizeIncrease ) // Use 0 if the size is not to increase { // // Cook book formula. // HANDLE hFile; VOID *pvRet; /* Returned to caller */ // If the file is to grow, it only makes sense to open it read/write. // if (0 != dwSizeIncrease && !bWriteEnable) { return NULL; } hFile = CreateFile( pchFileName, bWriteEnable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, //changed from open_existing FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); if ( INVALID_HANDLE_VALUE == hFile ) { return NULL; } // // If the caller wants to know the size (usually does) then get it now. // pvRet = pvFromHandle(hFile, bWriteEnable, pdwSizeFinal, dwSizeIncrease); BOOL fClose = CloseHandle( hFile ); _ASSERT( fClose ) ; return pvRet; } #ifdef DEBUG // // CMapFileEx: version with guard pages to be used only in DEBUG builds // to catch other threads writing into our memory ! // /* ------------------------------------------------------------------------ CMapFileEx::CMapFileEx Constructor when a file handle is available rather than a name. Note that it does not closes the handle Author Lindsay Harris - lindsayh History 16:14 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version to allow object tracking. Based on CarlK's function. ------------------------------------------------------------------------ */ CMapFileEx::CMapFileEx( HANDLE hFile, BOOL fWriteEnable, BOOL fTrack, DWORD cbIncrease ) { m_pv = NULL; m_cb = 0; // Set defaults. m_fFlags = 0; // None set yet. m_hFile = INVALID_HANDLE_VALUE; m_pvFrontGuard = NULL; m_cbFrontGuardSize = 0; m_pvRearGuard = NULL; m_cbRearGuardSize = 0; InitializeCriticalSection(&m_csProtectMap); wcsncpy( m_rgwchFileName, L"", MAX_PATH ); MapFromHandle( hFile, fWriteEnable, cbIncrease ); m_hFile = hFile; return; } /* ------------------------------------------------------------------------ CMapFileEx::~CMapFileEx Destructor. Two purposes, being to unmap the file, and optionally remove it from the track data. Author Lindsay Harris - lindsayh History 16:22 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] Numero Uno. ------------------------------------------------------------------------ */ CMapFileEx::~CMapFileEx( void ) { // // Unmap the file, if we succeeded in mapping it first! // // Lock EnterCriticalSection(&m_csProtectMap); if ( !(m_fFlags & MF_RELINQUISH) ) { // We're still controlling this file, so stick with it. // if ( m_pvFrontGuard ) { // get rid of guard pages DWORD dwOldProtect = PAGE_READONLY | PAGE_GUARD; if(!VirtualProtect( (LPVOID)m_pvFrontGuard, m_cbFrontGuardSize, PAGE_READWRITE, &dwOldProtect )) { _ASSERT( 1==0 ); goto CMapFileEx_Exit ; } if(!VirtualProtect( (LPVOID)m_pv, m_cb, PAGE_READWRITE, &dwOldProtect )) { _ASSERT( 1==0 ); goto CMapFileEx_Exit ; } if(!VirtualProtect( (LPVOID)m_pvRearGuard, m_cbRearGuardSize, PAGE_READWRITE, &dwOldProtect )) { _ASSERT( 1== 0 ); goto CMapFileEx_Exit ; } MoveMemory( m_pvFrontGuard, m_pv, m_cb ); FlushViewOfFile( m_pvFrontGuard, m_cb ) ; UnmapViewOfFile( (LPVOID)m_pvFrontGuard ); if( INVALID_HANDLE_VALUE != m_hFile ) { if( SetFilePointer( m_hFile, m_cb, NULL, FILE_BEGIN ) == m_cb ) { SetEndOfFile( m_hFile ) ; } } m_pvFrontGuard = m_pvRearGuard = m_pv = NULL ; } } CMapFileEx_Exit: LeaveCriticalSection(&m_csProtectMap); DeleteCriticalSection(&m_csProtectMap); return; } /* ------------------------------------------------------------------------ CMapFileEx::MapFromHandle Does the real work of mapping. Given a handle to the file, go through the motions of mapping, and recording what happens. Reports errors as needed. Also adjusts file size if requested. Author Lindsay Harris - lindsayh Carl Kadie - carlk History 16:30 on Mon 10 Apr 1995 -by- Lindsay Harris [lindsayh] First version, based on older code with CarlK enhancements. ------------------------------------------------------------------------ */ void CMapFileEx::MapFromHandle( HANDLE hFile, BOOL fWriteEnable, DWORD cbIncrease ) { if ( !fWriteEnable && cbIncrease != 0 ) return; // This is non-sensical. m_cb = GetFileSize( hFile, NULL ); DWORD cbNewSize = 0; // // Determine if the file is to grow. Only pass a non-zero size // to the system if the size is growing - it's probably faster, and // the most likely common case. // if ( cbIncrease ) { cbNewSize = m_cb += cbIncrease; } else { if ( m_cb == 0 ) return; // Nothing there. } if ( cbIncrease ) { _ASSERT(fWriteEnable); // // Make sure the file is the correct size. // DWORD fpos; BOOL fSetEnd; if ( (DWORD)-1 == ( fpos = SetFilePointer( hFile, cbNewSize, NULL, FILE_BEGIN )) || !(fSetEnd = SetEndOfFile( hFile )) ) { // // Error case // m_pv = NULL; return; } } // // Add guard page logic // SYSTEM_INFO si; GetSystemInfo(&si); DWORD dwPageSize = si.dwPageSize ; DWORD dwGuardPageSize = si.dwAllocationGranularity; // GuardPageSize should be > cbNewSize while( cbNewSize > dwGuardPageSize ) { dwGuardPageSize += si.dwAllocationGranularity; } // cbNewSize should be a multiple of dwPageSize, to ensure rear guard page is properly aligned _ASSERT( (cbNewSize % dwPageSize) == 0 ) ; DWORD cbAllocSize = (2 * (dwGuardPageSize)) + cbNewSize; DWORD dwOldProtect = PAGE_READWRITE ; DWORD dwError; // // Create the mapping object. // HANDLE hFileMap; // Intermediate step. hFileMap = CreateFileMapping( hFile, NULL, fWriteEnable ? PAGE_READWRITE : PAGE_READONLY, 0, cbAllocSize, // NOTE: this is greater than cbNewSize by 2*GuardPageSize NULL ); if ( !hFileMap ) { // Error case // m_pv = NULL; m_cb = 0; return; } // // Get the pointer mapped to the desired file. // m_pvFrontGuard = (LPBYTE)MapViewOfFile( hFileMap, fWriteEnable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, 0, 0 ); if ( !m_pvFrontGuard ) { // Error case // m_pv = NULL; m_cb = 0; // Also set to zero, just in case. goto MapFromHandle_Exit; } // front guard page of size (64KB) m_cbFrontGuardSize = dwGuardPageSize ; // actual memory-mapping m_pv = m_pvFrontGuard + m_cbFrontGuardSize ; MoveMemory( m_pv, m_pvFrontGuard, cbNewSize ); // rear guard page of size (64KB) m_pvRearGuard = m_pv + cbNewSize ; m_cbRearGuardSize = m_cbFrontGuardSize ; // make front page a guard page if(!VirtualProtect( (LPVOID)m_pvFrontGuard, m_cbFrontGuardSize, PAGE_READONLY | PAGE_GUARD, &dwOldProtect )) { m_pv = NULL; m_cb = 0; goto MapFromHandle_Exit ; } // make mapping read-only; users of CMapFileEx will need to use the // UnprotectMapping() / ProtectMapping() calls to write to this mapping. if(!VirtualProtect( (LPVOID)m_pv, cbNewSize, PAGE_READONLY, &dwOldProtect )) { m_pv = NULL; m_cb = 0; goto MapFromHandle_Exit ; } // make rear page a guard page if(!VirtualProtect( (LPVOID)m_pvRearGuard, m_cbRearGuardSize, PAGE_READONLY | PAGE_GUARD, &dwOldProtect )) { m_pv = NULL; m_cb = 0; goto MapFromHandle_Exit ; } MapFromHandle_Exit: dwError = GetLastError(); // // Now that we have our pointer, we can close the mapping object. // BOOL fClose = CloseHandle( hFileMap ); _ASSERT( fClose ); return; } /* ------------------------------------------------------------------------ CMapFileEx::UnprotectMapping Change mapping from READONLY to READWRITE when a write is necessary **** NOTE: Calls to UnprotectMapping() and ProtectMapping() should be matched *** eg: { UnprotectMapping(); // // code to write to the mapping // ProtectMapping(); } Returns TRUE on success, FALSE on failure Lock is held only if returns TRUE ------------------------------------------------------------------------ */ BOOL CMapFileEx::UnprotectMapping() { DWORD dwOldProtect = PAGE_READONLY; // *** This is released in ProtectMapping() *** EnterCriticalSection(&m_csProtectMap); // enable writes if(!VirtualProtect( (LPVOID)m_pv, m_cb, PAGE_READWRITE, &dwOldProtect )) { LeaveCriticalSection(&m_csProtectMap); return FALSE; } return TRUE; } /* ------------------------------------------------------------------------ CMapFileEx::UnprotectMapping This is called to revert the mapping protection back to READONLY **** The thread calling this function should have the protect lock ***** Returns TRUE on success, FALSE on failure Lock is released in either case ------------------------------------------------------------------------ */ BOOL CMapFileEx::ProtectMapping() { DWORD dwOldProtect = PAGE_READWRITE; BOOL fRet = TRUE; // disable writes if(!VirtualProtect( (LPVOID)m_pv, m_cb, PAGE_READONLY, &dwOldProtect )) { fRet = FALSE ; } LeaveCriticalSection(&m_csProtectMap); return fRet; } #endif // DEBUG