Beispiel #1
0
	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;
	}
Beispiel #2
0
	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;
	}