📄 udfscdfs.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//+-------------------------------------------------------------------------
//
//
// File: udfscdfs.cpp
//
// Contents:
//
// Classes:
//
// Functions:
//
//--------------------------------------------------------------------------
#include "udfs.h"
//+-------------------------------------------------------------------------
//
// Member: CCDFSFileSystem::DetectCreateAndInit
//
// Synopsis: Determines if the volume is an iso 9660 volume. If it is
// create an iso 9660 class and returns it initialized
//
// Arguments: [pCache] --
// [pRootDirectoryPointer] --
// [ppNewFS] --
//
// Returns: BOOL
//
// Notes:
//
//--------------------------------------------------------------------------
BYTE CCDFSFileSystem::DetectCreateAndInit( PUDFSDRIVER pDrv, PDIRECTORY_ENTRY pRootDirectoryPointer, CFileSystem** ppNewFS)
{
BOOL bResult;
// Try different locations to see if we can recognize a iso 9660 volume
bResult = DetectCreateAndInitAtLocation(45016, pDrv, pRootDirectoryPointer, ppNewFS);
if (bResult) {
return bResult;
}
bResult = DetectCreateAndInitAtLocation(45000, pDrv, pRootDirectoryPointer, ppNewFS);
if (bResult) {
return bResult;
}
bResult = DetectCreateAndInitAtLocation(16, pDrv, pRootDirectoryPointer, ppNewFS);
return bResult;
}
BOOL CCDFSFileSystem::DetectCreateAndInitAtLocation( DWORD dwInitialSector,PUDFSDRIVER pDrv, PDIRECTORY_ENTRY pRootDirectoryPointer, CFileSystem** ppNewFS)
{
BOOL fRet;
BOOL fFound;
DWORD dwSector;
BOOL fUnicodeFileSystem = FALSE;
BYTE buffer[CD_SECTOR_SIZE];
PISO9660_VOLUME_DESCRIPTOR pVD = (PISO9660_VOLUME_DESCRIPTOR)buffer;
memset( pVD, 0, sizeof(1)); // Prefix
//
// Read the volume descriptors
dwSector = dwInitialSector;
fFound = FALSE;
while (dwSector < dwInitialSector + MAX_SECTORS_TO_PROBE) {
fRet = pDrv->ReadDisk(dwSector, (PBYTE)pVD, CD_SECTOR_SIZE);
if (fRet == FALSE) {
break;
}
if (memcmp(&(pVD->ID), "CD001", 5) != 0) {
break;
}
if ((pVD->Type == 2) && ((pVD->EscapeSequence[0] == '%') && (pVD->EscapeSequence[1] == '/') && ((pVD->EscapeSequence[2] == '@') || (pVD->EscapeSequence[2] == 'C') || (pVD->EscapeSequence[2] == 'E')))) {
//
// Type == 2 then this is a supplemental volume
// descriptor. If we also find the escape sequence
// we looking for then this is a joliet file system
//
fUnicodeFileSystem = TRUE;
}
else if (pVD->Type == 1) {
//
// Type == 1 then this is a plain old primary pVD
// We need to keep looking for an svd.
//
fUnicodeFileSystem = FALSE;
}
else if (pVD->Type == 0xFF) {
//
// Type == ff signals the end.
//
break;
}
pRootDirectoryPointer->dwDiskSize = pVD->RootDirectory.ExtentSize;
pRootDirectoryPointer->dwDiskLocation = pVD->RootDirectory.ExtentLocation;
pRootDirectoryPointer->cbSize = sizeof(DIRECTORY_ENTRY);
pRootDirectoryPointer->pCacheLocation = NULL;
fFound = TRUE;
dwSector++;
//
// Save Volume Id
//
pDrv->SaveRootName((PCHAR)&pVD->Fill1[0x22],fUnicodeFileSystem); // TODO:
}
if (fFound == FALSE) {
SetLastError(ERROR_UNRECOGNIZED_MEDIA);
} else {
(*ppNewFS) = new CCDFSFileSystem(pDrv, fUnicodeFileSystem);
if ((*ppNewFS) == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
return fFound;
}
//+-------------------------------------------------------------------------
//
// Member: CCDFSFileSystem::ReadDirectory
//
// Synopsis: Parse the structures for this directory
//
// Arguments: [pszFullPath] -- The full pathname, to be stored
// in the header
// [pParentDirectoryEntry] -- The parent directory entry
//
// Returns: BOOL
//
// Notes:
//
//--------------------------------------------------------------------------
BOOL CCDFSFileSystem::ReadDirectory( LPWSTR pszFullPath, PDIRECTORY_ENTRY pParentDirectoryEntry)
{
PISO9660_DIRECTORY_RECORD pCurrentDiskDirectory;
PDIRECTORY_ENTRY pCurrentCacheEntry;
PDIRECTORY_HEADER pCacheHeader;
SYSTEMTIME SystemTime;
PBYTE pDiskBuffer;
PBYTE pCacheBuffer;
BOOL fRet;
int count;
DWORD dwBytesRead = 0;
DWORD dwFullPathSize= sizeof(DIRECTORY_HEADER) + (lstrlen(pszFullPath)+1) * sizeof(TCHAR) ;
//
// We only get to this point if this node has not been cached.
//
//
// Allocate enough memory to read the entire directory
//
ASSERT(m_pDriver);
pDiskBuffer = (PBYTE)UDFSAlloc(m_pDriver->m_hHeap, pParentDirectoryEntry->dwDiskSize);
if (pDiskBuffer == NULL) {
//
// shrink our cache
//
CompactAllHeaps();
pDiskBuffer = (PBYTE)UDFSAlloc(m_pDriver->m_hHeap, pParentDirectoryEntry->dwDiskSize);
if (pDiskBuffer == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
//
// Allocate more than enough memory
//
pCacheBuffer = (PBYTE)UDFSAlloc(m_pDriver->m_hHeap, max(pParentDirectoryEntry->dwDiskSize * 5,dwFullPathSize));
if (pCacheBuffer == NULL) {
CompactAllHeaps();
pCacheBuffer = (PBYTE)UDFSAlloc(m_pDriver->m_hHeap, max(pParentDirectoryEntry->dwDiskSize * 5,dwFullPathSize));
if (pCacheBuffer == NULL) {
UDFSFree(m_pDriver->m_hHeap, pDiskBuffer);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
//
// Create the header
//
pCacheHeader = (PDIRECTORY_HEADER)pCacheBuffer;
pCacheHeader->cbSize = ALIGN(sizeof(DIRECTORY_HEADER) + (lstrlen(pszFullPath) * sizeof(WCHAR)));
pCacheHeader->dwLockCount = 1;
pCacheHeader->pParent = pParentDirectoryEntry;
memcpy(&(pCacheHeader->Signature), DIR_HEADER_SIGNATURE, sizeof(pCacheHeader->Signature));
lstrcpy(pCacheHeader->szFullPath, pszFullPath);
pCurrentCacheEntry = (PDIRECTORY_ENTRY)(pCacheBuffer + pCacheHeader->cbSize);
fRet = m_pDriver->Read( pParentDirectoryEntry->dwDiskLocation, 0, pParentDirectoryEntry->dwDiskSize, pDiskBuffer, &dwBytesRead, NULL);
if ((fRet == FALSE) || (dwBytesRead != pParentDirectoryEntry->dwDiskSize)) {
goto Error;
}
//
// Skip the first two entries (current dir and parent dir)
//
pCurrentDiskDirectory = (PISO9660_DIRECTORY_RECORD)(pDiskBuffer + pDiskBuffer[0] + pDiskBuffer[pDiskBuffer[0]]);
//
// Parse the structures
//
while (TRUE) {
//
// Check to see if we're at the end of the directory
//
if ((pCurrentDiskDirectory->RecordLength == 0) ||
((((DWORD)pCurrentDiskDirectory) + pCurrentDiskDirectory->RecordLength) >
(((DWORD)pDiskBuffer) + pParentDirectoryEntry->dwDiskSize)))
{
pCurrentCacheEntry->cbSize = 0;
break;
}
//
// Copy information
//
pCurrentCacheEntry->dwDiskLocation = pCurrentDiskDirectory->ExtentLocation;
pCurrentCacheEntry->dwDiskSize = pCurrentDiskDirectory->ExtentSize;
if (pCurrentDiskDirectory->Flags & 2) {
pCurrentCacheEntry->fFlags = FILE_ATTRIBUTE_DIRECTORY;
} else {
pCurrentCacheEntry->fFlags = 0;
}
if (pCurrentDiskDirectory->Flags & 1) {
pCurrentCacheEntry->fFlags |= FILE_ATTRIBUTE_HIDDEN;
}
pCurrentCacheEntry->pCacheLocation = NULL;
pCurrentCacheEntry->pHeader = pCacheHeader;
pCurrentCacheEntry->cbSize = ALIGN(sizeof(DIRECTORY_ENTRY) + (pCurrentDiskDirectory->StrLen * sizeof(WCHAR)));
//
// Copy file time
//
SystemTime.wYear = pCurrentDiskDirectory->Time[0] + 1900;
SystemTime.wMonth = pCurrentDiskDirectory->Time[1];
SystemTime.wDay = pCurrentDiskDirectory->Time[2];
SystemTime.wHour = pCurrentDiskDirectory->Time[3];
SystemTime.wMinute = pCurrentDiskDirectory->Time[4];
SystemTime.wSecond = pCurrentDiskDirectory->Time[5];
SystemTime.wMilliseconds = 0; // ISO9660 doesn't expose milliseconds
SystemTimeToFileTime(&SystemTime, &pCurrentCacheEntry->Time);
//
// Copy file name
//
if (m_fUnicodeFileSystem == TRUE) {
for (count = 0; count < pCurrentDiskDirectory->StrLen; count+=2)
{
if (pCurrentDiskDirectory->FileName[count+1] == ';') {
break;
}
//
// convert from big to little endian (or the other way around)
//
pCurrentCacheEntry->szNameA[count] = pCurrentDiskDirectory->FileName[count+1];
pCurrentCacheEntry->szNameA[count+1] = pCurrentDiskDirectory->FileName[count];
}
DEBUGMSG( ZONE_FUNCTION, (TEXT("UDFS!CFileSystem::ReadDirectory Filename: %s\n"), pCurrentCacheEntry->szNameW));
while( count > 0 && *((WCHAR*)&pCurrentCacheEntry->szNameA[count-2]) == L'.' ) {
count -= 2;
}
pCurrentCacheEntry->szNameA[count] = 0;
pCurrentCacheEntry->szNameA[count + 1] = 0;
} else {
pCurrentCacheEntry->fFlags |= IS_ANSI_FILENAME;
for (count = 0; count < pCurrentDiskDirectory->StrLen; count++) {
if (pCurrentDiskDirectory->FileName[count] == ';') {
break;
}
pCurrentCacheEntry->szNameA[count] = pCurrentDiskDirectory->FileName[count];
}
while( count > 0 && pCurrentCacheEntry->szNameA[count-1] == '.' ) {
--count;
}
pCurrentCacheEntry->szNameA[count] = 0;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("UDFS!CFileSystem::ReadDirectory Moving disk %d\n"), pCurrentDiskDirectory->RecordLength));
DEBUGMSG(ZONE_FUNCTION, (TEXT("UDFS!CFileSystem::ReadDirectory Moving cache %d\n"), pCurrentCacheEntry->cbSize));
//
// Update the cache end
//
pCurrentCacheEntry = NextDirectoryEntry(pCurrentCacheEntry);
pCurrentDiskDirectory = (PISO9660_DIRECTORY_RECORD) ((PBYTE)pCurrentDiskDirectory + pCurrentDiskDirectory->RecordLength);
if (pCurrentDiskDirectory->RecordLength == 0) {
PISO9660_DIRECTORY_RECORD pProposedRecord;
//
// If we hit a null length record we may be on a sector
// boundary. Move the pointer up to the next sector only
// if this doesn't put us beyond the end of the disk
// buffer.
//
DWORD dwOffset = (((PBYTE)pCurrentDiskDirectory - pDiskBuffer + (CD_SECTOR_SIZE-1)) & ~(CD_SECTOR_SIZE-1));
pProposedRecord = (PISO9660_DIRECTORY_RECORD) ((PBYTE)pDiskBuffer + dwOffset);
DEBUGMSG(ZONE_FUNCTION, (TEXT("UDFS!CFileSystem::ReadDirectory Moving disk manually due to null length record: %d\r\n"), (PBYTE) pProposedRecord - (PBYTE) pCurrentDiskDirectory));
if ((DWORD) pProposedRecord < ((DWORD) pDiskBuffer + pParentDirectoryEntry->dwDiskSize - 1)) {
pCurrentDiskDirectory = pProposedRecord;
}
}
}
Error:
UDFSFree(m_pDriver->m_hHeap, pDiskBuffer);
if (fRet == FALSE) {
UDFSFree(m_pDriver->m_hHeap, pCacheBuffer);
} else {
pParentDirectoryEntry->pCacheLocation =
(PDIRECTORY_ENTRY)UDFSReAlloc( m_pDriver->m_hHeap, pCacheBuffer, ((DWORD)pCurrentCacheEntry - (DWORD)pCacheBuffer) + sizeof(pCurrentCacheEntry->cbSize));
if (!pParentDirectoryEntry->pCacheLocation) {
UDFSFree( m_pDriver->m_hHeap, pCacheBuffer);
fRet = FALSE;
}
}
return fRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -