/* $Id$ * * * FILE: DirEntry.c * PURPOSE: Routines to manipulate directory entries. * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * Rex Jolliff (rex@lvcablemodem.com) */ /* ------------------------------------------------------- INCLUDES */ #include #include #include #define NDEBUG #include #include "vfat.h" #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry)) ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, PFAT_DIR_ENTRY pFatDirEntry) { ULONG cluster; if (pDeviceExt->FatInfo.FatType == FAT32) { cluster = pFatDirEntry->FirstCluster + pFatDirEntry->FirstClusterHigh * 65536; } else { cluster = pFatDirEntry->FirstCluster; } return cluster; } BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry) { return pFatDirEntry->Filename [0] == 0xe5; } BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry) { return pFatDirEntry->Filename [0] == 0; } BOOL vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry) { return pFatDirEntry->Attrib == 0x0f; } BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry) { return 0x08 == (pFatDirEntry->Attrib & 0x1f); } void vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName) { vfat8Dot3ToString (dirEntry, entryName); } NTSTATUS vfatGetNextDirEntry(PVOID * pContext, PVOID * pPage, IN PVFATFCB pDirFcb, IN OUT PULONG pDirIndex, OUT PWSTR pFileName, OUT PFAT_DIR_ENTRY pDirEntry, OUT PULONG pStartIndex) { ULONG dirMap; PWCHAR pName; LARGE_INTEGER FileOffset; FATDirEntry * fatDirEntry; slot * longNameEntry; ULONG index; *pFileName = 0; FileOffset.u.HighPart = 0; FileOffset.u.LowPart = ROUND_DOWN(*pDirIndex * sizeof(FATDirEntry), PAGE_SIZE); if (*pContext == NULL || (*pDirIndex % ENTRIES_PER_PAGE) == 0) { if (*pContext != NULL) { CcUnpinData(*pContext); } if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { *pContext = NULL; return STATUS_NO_MORE_ENTRIES; } } fatDirEntry = (FATDirEntry*)(*pPage) + *pDirIndex % ENTRIES_PER_PAGE; longNameEntry = (slot*) fatDirEntry; dirMap = 0; if (pStartIndex) { *pStartIndex = *pDirIndex; } while (TRUE) { if (vfatIsDirEntryEndMarker(fatDirEntry)) { CcUnpinData(*pContext); *pContext = NULL; return STATUS_NO_MORE_ENTRIES; } if (vfatIsDirEntryDeleted (fatDirEntry)) { dirMap = 0; *pFileName = 0; if (pStartIndex) { *pStartIndex = *pDirIndex + 1; } } else { if (vfatIsDirEntryLongName (fatDirEntry)) { if (dirMap == 0) { DPRINT (" long name entry found at %d\n", *pDirIndex); memset(pFileName, 0, 256 * sizeof(WCHAR)); } DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", 5, longNameEntry->name0_4, 6, longNameEntry->name5_10, 2, longNameEntry->name11_12); index = (longNameEntry->id & 0x1f) - 1; dirMap |= 1 << index; pName = pFileName + 13 * index; memcpy(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR)); memcpy(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR)); memcpy(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR)); DPRINT (" longName: [%S]\n", pFileName); } else { memcpy (pDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY)); break; } } (*pDirIndex)++; if ((*pDirIndex % ENTRIES_PER_PAGE) == 0) { CcUnpinData(*pContext); FileOffset.u.LowPart += PAGE_SIZE; if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) { CHECKPOINT; *pContext = NULL; return STATUS_NO_MORE_ENTRIES; } fatDirEntry = (FATDirEntry*)*pPage; longNameEntry = (slot*) *pPage; } else { fatDirEntry++; longNameEntry++; } } return STATUS_SUCCESS; }