2002-10-01 19:27:25 +00:00
|
|
|
/* $Id: direntry.c,v 1.9 2002/10/01 19:27:17 chorns Exp $
|
2001-07-05 01:51:53 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* 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 <ddk/ntddk.h>
|
|
|
|
#include <wchar.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2002-10-01 19:27:25 +00:00
|
|
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
|
|
|
|
(pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
|
2001-07-13 10:31:14 +00:00
|
|
|
|
|
|
|
#define ENTRIES_PER_CACHEPAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
|
2002-03-18 22:37:13 +00:00
|
|
|
(CACHEPAGESIZE(pDeviceExt) / ((pDeviceExt)->FatInfo.BytesPerSector)))
|
2001-07-13 10:31:14 +00:00
|
|
|
|
2001-07-05 01:51:53 +00:00
|
|
|
|
|
|
|
ULONG
|
|
|
|
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
|
|
|
PFAT_DIR_ENTRY pFatDirEntry)
|
|
|
|
{
|
|
|
|
ULONG cluster;
|
|
|
|
|
2002-03-18 22:37:13 +00:00
|
|
|
if (pDeviceExt->FatInfo.FatType == FAT32)
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2001-07-28 07:05:56 +00:00
|
|
|
BOOL
|
|
|
|
vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
|
|
|
|
{
|
|
|
|
return pFatDirEntry->Attrib == 0x28;
|
|
|
|
}
|
|
|
|
|
2001-07-05 01:51:53 +00:00
|
|
|
void
|
|
|
|
vfatGetDirEntryName (PFAT_DIR_ENTRY dirEntry, PWSTR entryName)
|
|
|
|
{
|
|
|
|
vfat8Dot3ToString (dirEntry->Filename, dirEntry->Ext, entryName);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
|
|
|
|
PVFATFCB pDirectoryFCB,
|
|
|
|
ULONG * pDirectoryIndex,
|
|
|
|
PWSTR pLongFileName,
|
|
|
|
PFAT_DIR_ENTRY pDirEntry)
|
|
|
|
{
|
2001-07-13 10:31:14 +00:00
|
|
|
ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_CACHEPAGE(pDeviceExt);
|
|
|
|
ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_CACHEPAGE(pDeviceExt);
|
2001-07-05 01:51:53 +00:00
|
|
|
PVOID currentPage = NULL;
|
|
|
|
FATDirEntry * fatDirEntry;
|
|
|
|
slot * longNameEntry;
|
|
|
|
ULONG cpos;
|
2001-10-10 22:14:34 +00:00
|
|
|
LARGE_INTEGER FileOffset;
|
|
|
|
PVOID Context;
|
2001-07-05 01:51:53 +00:00
|
|
|
|
|
|
|
DPRINT ("vfatGetNextDirEntry (%x,%x,%d,%x,%x)\n",
|
|
|
|
pDeviceExt,
|
|
|
|
pDirectoryFCB,
|
|
|
|
*pDirectoryIndex,
|
|
|
|
pLongFileName,
|
|
|
|
pDirEntry);
|
|
|
|
|
|
|
|
*pLongFileName = 0;
|
|
|
|
|
2001-10-10 22:14:34 +00:00
|
|
|
FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
|
|
|
|
if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
|
|
|
|
CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage))
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
2001-10-10 22:14:34 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
fatDirEntry = (FATDirEntry *) currentPage;
|
|
|
|
|
|
|
|
if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage]))
|
|
|
|
{
|
|
|
|
DPRINT ("end of directory, returning no more entries\n");
|
2001-10-10 22:14:34 +00:00
|
|
|
CcUnpinData(Context);
|
2001-07-05 01:51:53 +00:00
|
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
|
|
}
|
2001-08-01 15:59:24 +00:00
|
|
|
else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage])
|
|
|
|
&& !vfatIsDirEntryDeleted (&fatDirEntry [indexInPage]))
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
|
|
|
DPRINT (" long name entry found at %d\n", *pDirectoryIndex);
|
|
|
|
longNameEntry = (slot *) currentPage;
|
|
|
|
|
|
|
|
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
|
|
|
|
5, longNameEntry [indexInPage].name0_4,
|
|
|
|
6, longNameEntry [indexInPage].name5_10,
|
|
|
|
2, longNameEntry [indexInPage].name11_12);
|
|
|
|
|
|
|
|
vfat_initstr (pLongFileName, 256);
|
|
|
|
vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
|
|
|
|
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
|
|
|
|
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
|
|
|
|
|
|
|
|
DPRINT (" longName: [%S]\n", pLongFileName);
|
|
|
|
|
|
|
|
cpos = 0;
|
2001-08-01 15:59:24 +00:00
|
|
|
while ((longNameEntry [indexInPage].id != 0x41) &&
|
2001-07-05 01:51:53 +00:00
|
|
|
(longNameEntry [indexInPage].id != 0x01) &&
|
|
|
|
(longNameEntry [indexInPage].attr > 0))
|
|
|
|
{
|
|
|
|
(*pDirectoryIndex)++;
|
|
|
|
indexInPage++;
|
2001-07-13 10:31:14 +00:00
|
|
|
if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
|
|
|
indexInPage = 0;
|
|
|
|
pageNumber++;
|
|
|
|
|
2001-10-10 22:14:34 +00:00
|
|
|
CcUnpinData(Context);
|
|
|
|
FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
|
|
|
|
if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
|
|
|
|
CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage))
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
2001-10-10 22:14:34 +00:00
|
|
|
return STATUS_UNSUCCESSFUL;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
longNameEntry = (slot *) currentPage;
|
|
|
|
}
|
|
|
|
DPRINT (" index %d\n", *pDirectoryIndex);
|
|
|
|
|
|
|
|
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
|
|
|
|
5, longNameEntry [indexInPage].name0_4,
|
|
|
|
6, longNameEntry [indexInPage].name5_10,
|
|
|
|
2, longNameEntry [indexInPage].name11_12);
|
|
|
|
|
|
|
|
cpos++;
|
|
|
|
vfat_movstr (pLongFileName, 13, 0, cpos * 13);
|
|
|
|
vfat_wcsncpy (pLongFileName, longNameEntry [indexInPage].name0_4, 5);
|
|
|
|
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name5_10, 5, 6);
|
|
|
|
vfat_wcsncat (pLongFileName, longNameEntry [indexInPage].name11_12, 11, 2);
|
|
|
|
|
|
|
|
DPRINT (" longName: [%S]\n", pLongFileName);
|
|
|
|
|
|
|
|
}
|
|
|
|
(*pDirectoryIndex)++;
|
|
|
|
indexInPage++;
|
2001-07-13 10:31:14 +00:00
|
|
|
if (indexInPage == ENTRIES_PER_CACHEPAGE(pDeviceExt))
|
2001-07-05 01:51:53 +00:00
|
|
|
{
|
|
|
|
indexInPage = 0;
|
|
|
|
pageNumber++;
|
|
|
|
|
2001-10-10 22:14:34 +00:00
|
|
|
CcUnpinData(Context);
|
|
|
|
FileOffset.QuadPart = pageNumber * CACHEPAGESIZE(pDeviceExt);
|
|
|
|
if (!CcMapData(pDirectoryFCB->FileObject, &FileOffset,
|
|
|
|
CACHEPAGESIZE(pDeviceExt), TRUE, &Context, ¤tPage))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY));
|
|
|
|
(*pDirectoryIndex)++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-10-10 22:14:34 +00:00
|
|
|
CcUnpinData(Context);
|
|
|
|
return STATUS_SUCCESS;
|
2001-07-05 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|