bool ISO9660::ReadDirectoryBlock(ISO9660_DirectoryEntry *pDirectoryEntry, FileSystemDirectoryEntry *pParentDirectory, bool bVerbose) { // Check if this directory entry has already been cached. FileSystemSectorCacheEntry *pCacheEntry = (FileSystemSectorCacheEntry*)FindCacheEntry(pDirectoryEntry->dwExtentLBA.LE); if (pCacheEntry != nullptr) { // The directory entry has already been cached so there is nothing to do here. return true; } // Create a new FileSystemDirectoryEntry object for the directory entry provided. FileSystemDirectoryEntry *pFsDirectoryEntry = new FileSystemDirectoryEntry(pDirectoryEntry, pParentDirectory); if (bVerbose == true) { // Print the folder name. if (pFsDirectoryEntry->IsDirectory() == true) printf("%d\t\t%d\t\t%s\\..\n", pFsDirectoryEntry->GetExtentLBA(), pFsDirectoryEntry->GetExtentSize(), pFsDirectoryEntry->GetFullName()); } // The directory entry has not been cached yet so add it to the directory cache. if (AddToCache(pFsDirectoryEntry, &pCacheEntry) == false) { // Failed to cache directory entry data. delete pDirectoryEntry; return false; } // If this is a root entry then add it to our list of root directory entries. if (pParentDirectory == nullptr) { // This is a root entry so add it to the root list. this->lDirectoryEntries.push_back(pFsDirectoryEntry); } // Initialize the loop counter and interator. DWORD dwRemainingData = pDirectoryEntry->dwExtentSize.LE; PBYTE pbCacheData = pCacheEntry->pbSectorData; // Loop through the directory sectors until we reach the last directory entry. do { // Get the next ISO9660 directory entry from the cache data. ISO9660_DirectoryEntry *pDirEntry = (ISO9660_DirectoryEntry*)pbCacheData; // Check if the current directory entry is valid or if we are on a sector boundary. if (pDirEntry->bEntryLength == 0) { // Check if this next entry would cross a sector boundary. DWORD dwRemainder = dwRemainingData % ISO9660_SECTOR_SIZE; if (dwRemainder > 0 && dwRemainder < ISO9660_DIR_ENTRY_MAX_SIZE) { // Skip to the next sector. dwRemainingData -= dwRemainder; pbCacheData += dwRemainder; // Check to see if there is any remaining data left to be parsed. if (dwRemainingData <= 0) break; // Update the entry pointer. pDirEntry = (ISO9660_DirectoryEntry*)pbCacheData; } // Double check we now have a valid entry to work with. if (pDirEntry->bEntryLength == 0) break; } // Check if this entry is a directory or a file. if ((pDirEntry->bFileFlags & FileFlags::FileIsDirectory) != 0) { // Make sure we don't print the entry for the "./" file entry. if (pDirEntry->dwExtentLBA.LE != pDirectoryEntry->dwExtentLBA.LE) { // Recursively parse the child directory. if (ReadDirectoryBlock(pDirEntry, pFsDirectoryEntry, bVerbose) == false) { // Failed to read child directory entry data. return false; } } } else { // Setup the fs child entry which will automatically add it to the parent's list of children. FileSystemDirectoryEntry *pEntry = new FileSystemDirectoryEntry(pDirEntry, pFsDirectoryEntry); // Check if we should print the file information. if (bVerbose == true) printf("%d\t\t%d\t\t%s\n", pDirEntry->dwExtentLBA.LE, pDirEntry->dwExtentSize.LE, pEntry->GetFullName()); } // Next entry. dwRemainingData -= pDirEntry->bEntryLength; pbCacheData += pDirEntry->bEntryLength; } while (dwRemainingData > 0); // Successfully parsed the file system for this directory entry. return true; }
bool ISO9660::AddToCache(FileSystemDirectoryEntry *pDirectoryEntry, FileSystemSectorCacheEntry **ppCacheEntry) { DWORD dwBytesRead = 0; // Check to see if there is already a cache entry for this directory. *ppCacheEntry = (FileSystemSectorCacheEntry*)FindCacheEntry(pDirectoryEntry->pValue->dwExtentLBA.LE); if (*ppCacheEntry != nullptr) { // There is already a cache entry for this directory entry, so we are done here. return true; } // Initialize a new FileSystemSectorCacheEntry object. FileSystemSectorCacheEntry *pCacheEntry = new FileSystemSectorCacheEntry(); pCacheEntry->dwExtentLBA = pDirectoryEntry->pValue->dwExtentLBA.LE; pCacheEntry->dwExtentSize = pDirectoryEntry->pValue->dwExtentSize.LE; pCacheEntry->sFileIdentifier = pDirectoryEntry->sName; // Allocate the cache buffer for the directory entry. pCacheEntry->pbSectorData = (PBYTE)VirtualAlloc(NULL, pCacheEntry->dwExtentSize, MEM_COMMIT, PAGE_READWRITE); if (pCacheEntry->pbSectorData == NULL) { // Failed to allocate cache buffer. printf("ISO9660::AddToCache(): failed to allocate cache buffer for entry '%s'!\n", pCacheEntry->sFileIdentifier); goto Cleanup; } // Check if we are reading from a file or from a CDI image. if (this->m_hFileHandle != INVALID_HANDLE_VALUE) { // Compute the directory entry data offset and seek to it. int dwDataOffset = (pCacheEntry->dwExtentLBA - this->m_dwLBA) * ISO9660_SECTOR_SIZE; SetFilePointer(this->m_hFileHandle, dwDataOffset, NULL, FILE_BEGIN); // Read the directory data into the cache buffer. if (ReadFile(this->m_hFileHandle, pCacheEntry->pbSectorData, pCacheEntry->dwExtentSize, &dwBytesRead, NULL) == false || dwBytesRead != pCacheEntry->dwExtentSize) { // Failed to read the directory data into the cache buffer. printf("ISO9660::AddToCache(): failed to read directory data for entry '%s'!\n", pCacheEntry->sFileIdentifier); goto Cleanup; } } else { // Read the directory data into the cache buffer. if (this->m_phTrackHandle->ReadData(pCacheEntry->dwExtentLBA - this->m_dwLBA, pCacheEntry->pbSectorData, pCacheEntry->dwExtentSize) == false) { // Failed to read the directory data into the cache buffer. printf("ISO9660::AddToCache(): failed to read directory data for entry '%s'!\n", pCacheEntry->sFileIdentifier); goto Cleanup; } } // Add the new cache entry object to the list. this->lSectorCache.push_back(pCacheEntry); // Successfully cached the directory data, assign the cache entry pointer and return true. *ppCacheEntry = pCacheEntry; return true; Cleanup: if (pCacheEntry) { // Check if the cache buffer was allocated. if (pCacheEntry->pbSectorData) VirtualFree(pCacheEntry->pbSectorData, pCacheEntry->dwExtentSize, MEM_DECOMMIT); // Free the cache entry object. delete pCacheEntry; } // Done with errors, return false. return false; }
CObjectImageArray &CCompositeImageDesc::GetImage (const CCompositeImageSelector &Selector, DWORD dwModifiers, int *retiRotation) const // GetImage // // Returns the image { CCompositeImageSelector::ETypes iType = Selector.GetType(DEFAULT_SELECTOR_ID); // If the selector has a wreck image, then we use that if (iType == CCompositeImageSelector::typeShipClass) { if (retiRotation) *retiRotation = Selector.GetVariant(DEFAULT_SELECTOR_ID); return Selector.GetShipwreckImage(DEFAULT_SELECTOR_ID); } // If the selector has an item image, then we use that else if (iType == CCompositeImageSelector::typeItemType) { if (retiRotation) *retiRotation = 0; return Selector.GetFlotsamImage(DEFAULT_SELECTOR_ID); } // Get the image from the root entry else if (m_pRoot) { // retiRotation is used as the vertical index into the image. // Since each variant is expected to be its own image, we set to 0. if (retiRotation) *retiRotation = 0; // Look in the cache SCacheEntry *pEntry = FindCacheEntry(Selector, dwModifiers); if (pEntry) return pEntry->Image; // If not in the cache, add a new entry pEntry = m_Cache.Insert(); pEntry->Selector = Selector; pEntry->dwModifiers = dwModifiers; m_pRoot->GetImage(Selector, &pEntry->Image); // Apply modifiers if (dwModifiers) ApplyModifiers(dwModifiers, &pEntry->Image); // Done return pEntry->Image; } else return EMPTY_IMAGE; }