/*++ Copyright (c) 1994 Microsoft Corporation Module Name: filemap.hxx Abstract: contains class definitions for memory mapped file (MEMMAP_FILE) class objects. Author: Madan Appiah (madana) 28-April-1995 Environment: User Mode - Win32 Revision History: --*/ #define NUM_BITS_IN_DWORD (sizeof(DWORD) * 8) /*++ Class Description: Class that maps the URL object containter to a memory mapped file. Private Member functions: ValidateCache : this private function validate the cache when the cache is read to memory first time. Public Member functions: GetStatus : returns status of the object. AllocateEntry FreeEntry FindNextEntry : Find next entry in the URL list. GetHeapStart : returns start of the virtual memory address. --*/ // // ----------------- Memory map file header -----------------------------// // #define DIR_NAME_SIZE 8 struct CacheDir { DWORD nFileCount; CHAR sDirName[DIR_NAME_SIZE]; }; typedef struct _MEMMAP_HEADER_SMALL { TCHAR FileSignature[MAX_SIG_SIZE]; DWORD FileSize; DWORD dwHashTableOffset; DWORD NumUrlInternalEntries; DWORD NumUrlEntriesAlloced; // DWORD dwGarbage; // due to /Zp8 struct alignment LONGLONG CacheLimit; LONGLONG CacheSize; LONGLONG ExemptUsage; DWORD nDirCount; CacheDir DirArray[DEFAULT_MAX_DIRS]; DWORD dwHeaderData[NUM_HEADER_DATA_DWORDS]; } MEMMAP_HEADER_SMALL; #define BIT_MAP_ARRAY_SIZE (((HEADER_ENTRY_SIZE - sizeof(MEMMAP_HEADER_SMALL)))/sizeof(DWORD)) typedef struct _MEMMAP_HEADER : _MEMMAP_HEADER_SMALL { DWORD AllocationBitMap[BIT_MAP_ARRAY_SIZE]; } MEMMAP_HEADER, *LPMEMMAP_HEADER; class MEMMAP_FILE { private: DWORD _Status; // // parameters that passed as object create. // DWORD _EntrySize; BOOL _PerUser; // TRUE if unshared per-user container. LPTSTR _FullPathName; // full path name of the cache directory. DWORD _FullPathNameLen; // full path name string length. LPTSTR _FileName; // full path name of the memory mapped file. DWORD _FileSize; // current size of the memory mapped file. HANDLE _FileHandle; // file handle of the memory mapped file. HANDLE _FileMappingHandle; // mapping object handle LPVOID _BaseAddr; LPMEMMAP_HEADER _HeaderInfo; LPBYTE _EntryArray; DWORD _NumBitMapDWords; BOOL _NewFile; BOOL ValidateCache( VOID ); DWORD GrowMapFile( DWORD ); DWORD GetAndSetNextFreeEntry( DWORD ); BOOL CheckNextNBits(DWORD&, DWORD&, DWORD, DWORD&); BOOL SetNextNBits(DWORD, DWORD, DWORD); DWORD RemapAddress( VOID ); DWORD DeleteFiles( LPTSTR Files ); BOOL InitHeaderInfo( VOID ); public: MEMMAP_FILE() {} ~MEMMAP_FILE( VOID ); MemMapStatus Init(LPTSTR PathName, DWORD EntrySize, BOOL PerUser); void CloseMapping(void); BOOL Reinitialize(void); BOOL ReAllocateEntry(LPFILEMAP_ENTRY, DWORD); LPFILEMAP_ENTRY AllocateEntry(DWORD); LPFILEMAP_ENTRY FindNextEntry (DWORD* pdwEnum, DWORD dwFilter, GROUPID GroupId, DWORD dwMatch = 0); BOOL FreeEntry(LPFILEMAP_ENTRY Entry); DWORD CheckSizeGrowAndRemapAddress(VOID); BOOL IsBadOffset (DWORD dwOffset); URL_FILEMAP_ENTRY* ValidateUrlOffset(DWORD dwOffset); BOOL IsBadGroupOffset(DWORD dwOffset); GROUP_ENTRY* ValidateGroupOffset(DWORD dwOffset, HASH_ITEM* hItem); LIST_GROUP_ENTRY* ValidateListGroupOffset(DWORD dwOffset); // // WARNING: URL_CONTAINER::CleanupAllUrls assumes // that Handle is really an offset to a HASH_ITEM*. // LPBYTE *GetHeapStart(VOID) { return( (LPBYTE *)&_BaseAddr ); } LPDWORD GetPtrToHashTableOffset (VOID) { return &_HeaderInfo->dwHashTableOffset; } LPDWORD GetPtrToLeakListOffset (VOID) { return _HeaderInfo->dwHeaderData + CACHE_HEADER_DATA_ROOT_LEAK_OFFSET; } // // --------- Inline directory related funcs ------------------ // DWORD GetFileCount(DWORD idx) { return _HeaderInfo->DirArray[idx].nFileCount; } VOID SetFileCount(DWORD idx, DWORD nFiles) { if (idx < DEFAULT_MAX_DIRS) _HeaderInfo->DirArray[idx].nFileCount = nFiles; else INET_ASSERT(FALSE); } VOID IncrementFileCount(DWORD idx) { if (idx < DEFAULT_MAX_DIRS) _HeaderInfo->DirArray[idx].nFileCount++; else INET_ASSERT(FALSE); } VOID DecrementFileCount(DWORD idx) { if (idx < DEFAULT_MAX_DIRS) _HeaderInfo->DirArray[idx].nFileCount--; else INET_ASSERT(FALSE); } DWORD GetDirCount() { return _HeaderInfo->nDirCount; } VOID SetDirCount(DWORD nDirCount) { _HeaderInfo->nDirCount = nDirCount; } VOID IncrementDirCount() { _HeaderInfo->nDirCount++; } VOID DecrementDirCount() { _HeaderInfo->nDirCount--; } VOID SetDirName(DWORD idx, LPSTR sDirName) { INET_ASSERT(strlen(sDirName) == DIR_NAME_SIZE); if (idx < DEFAULT_MAX_DIRS) memcpy(_HeaderInfo->DirArray[idx].sDirName, sDirName, DIR_NAME_SIZE); else INET_ASSERT(FALSE); } VOID GetDirName(DWORD idx, LPSTR szDirName) { memcpy(szDirName, _HeaderInfo->DirArray[idx].sDirName, DIR_NAME_SIZE); szDirName[DIR_NAME_SIZE] = '\0'; } DWORD GetDirIndex(LPSTR szDirName) { CHAR* ptr = szDirName + strlen(_FullPathName); for (DWORD idx = 0; idx < _HeaderInfo->nDirCount; idx++) if (!strnicmp(ptr, _HeaderInfo->DirArray[idx].sDirName, DIR_NAME_SIZE)) return idx; return NOT_A_CACHE_SUBDIRECTORY; } //Creates a cache directory with a given name to allow existing directories //to be copied into another cache file. Just the eight letters of the new //directory are given. BOOL CreateDirWithSecureName( LPSTR szDirName) { BOOL retVal = FALSE; CHAR szFullDirName[MAX_PATH]; DWORD nNewDir; // MEMMAP_FILE::GetDirIndex requires the full directory name memcpy( szFullDirName, _FullPathName, _FullPathNameLen); lstrcpy( szFullDirName + _FullPathNameLen, szDirName); // only try to add the subdirectory if it doesn't already exist.. if( GetDirIndex( szFullDirName) != NOT_A_CACHE_SUBDIRECTORY) goto exitCreateDirWithSecureName; // don't create more than DEFAULT_MAX_DIRS directories if( (nNewDir = GetDirCount()) >= DEFAULT_MAX_DIRS) goto exitCreateDirWithSecureName; IncrementDirCount(); SetDirName( nNewDir, szDirName); SetFileCount( nNewDir, 0); retVal = TRUE; exitCreateDirWithSecureName: return retVal; } // // --------- General Get/Set type routines ------------------ // DWORD GetStatus( VOID ) { return( _Status ); } DWORD IsNewFile( VOID ) { return( _NewFile ); } LPSTR GetFullPathName() { return _FullPathName; } DWORD GetFullPathNameLen() { return _FullPathNameLen; } LONGLONG GetCacheSize() { return _HeaderInfo->CacheSize + _FileSize; } LONGLONG GetCacheLimit() { return(_HeaderInfo->CacheLimit); } LONGLONG GetExemptUsage() { return _HeaderInfo->ExemptUsage; } VOID SetCacheLimit(LONGLONG CacheLimit) { _HeaderInfo->CacheLimit = CacheLimit; } VOID AdjustCacheSize(LONGLONG DeltaSize) { if (_HeaderInfo->CacheSize >= -DeltaSize) _HeaderInfo->CacheSize += DeltaSize; else { // INET_ASSERT (FALSE); // underflow _HeaderInfo->CacheSize = 0; } } VOID SetCacheSize(LONGLONG Delta) { INET_ASSERT((Delta>=0)); _HeaderInfo->CacheSize = (Delta>=0) ? Delta : 0; } VOID AdjustExemptUsage (LONGLONG DeltaSize) { if (_HeaderInfo->ExemptUsage >= -DeltaSize) _HeaderInfo->ExemptUsage += DeltaSize; else { // INET_ASSERT (FALSE); // underflow _HeaderInfo->ExemptUsage = 0; } } BOOL SetHeaderData(DWORD nIdx, DWORD dwData) { INET_ASSERT(nIdx < NUM_HEADER_DATA_DWORDS); _HeaderInfo->dwHeaderData[nIdx] = dwData; return TRUE; } BOOL GetHeaderData(DWORD nIdx, LPDWORD pdwData) { INET_ASSERT(nIdx < NUM_HEADER_DATA_DWORDS); *pdwData = _HeaderInfo->dwHeaderData[nIdx]; return TRUE; } BOOL IncrementHeaderData(DWORD nIdx, LPDWORD pdwData) { INET_ASSERT(nIdx < NUM_HEADER_DATA_DWORDS); *pdwData = _HeaderInfo->dwHeaderData[nIdx]; ++*pdwData; _HeaderInfo->dwHeaderData[nIdx] = *pdwData; return TRUE; } VOID ResetEntryData(LPFILEMAP_ENTRY Entry, DWORD dwResetValue, DWORD nBlocks) { for (DWORD i = 0; i < (_EntrySize * nBlocks) / sizeof(DWORD); i++) { *((DWORD*) Entry + i) = dwResetValue; } } };