mirror of
https://github.com/reactos/reactos.git
synced 2024-07-03 03:04:22 +00:00
Partial directory caching (create calls cached, but dir info calls
still use non cached routines). svn path=/trunk/; revision=2038
This commit is contained in:
parent
52ead14335
commit
208eecc0f4
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: create.c,v 1.26 2001/06/14 21:05:08 jfilby Exp $
|
/* $Id: create.c,v 1.27 2001/07/05 01:51:52 rex Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -21,10 +21,6 @@
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
|
||||||
|
|
||||||
#define TAG_CCB TAG('V', 'C', 'C', 'B')
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
|
@ -60,7 +56,7 @@ IsDeletedEntry (PVOID Block, ULONG Offset)
|
||||||
(((FATDirEntry *) Block)[Offset].Filename[0] == 0));
|
(((FATDirEntry *) Block)[Offset].Filename[0] == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
|
void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName)
|
||||||
{
|
{
|
||||||
int fromIndex, toIndex;
|
int fromIndex, toIndex;
|
||||||
|
|
||||||
|
@ -475,196 +471,57 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||||
* FUNCTION: Opens a file
|
* FUNCTION: Opens a file
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PWSTR current = NULL;
|
|
||||||
PWSTR next;
|
|
||||||
PWSTR string;
|
|
||||||
// PWSTR buffer; // used to store a pointer while checking MAX_PATH conformance
|
|
||||||
PVFATFCB ParentFcb;
|
PVFATFCB ParentFcb;
|
||||||
PVFATFCB Fcb;
|
PVFATFCB Fcb;
|
||||||
PVFATFCB Temp;
|
|
||||||
PVFATCCB newCCB;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PWSTR AbsFileName = NULL;
|
PWSTR AbsFileName = NULL;
|
||||||
ULONG BytesPerCluster, FileCacheQuantum;
|
|
||||||
|
|
||||||
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
|
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
|
||||||
|
|
||||||
/* FIXME : treat relative name */
|
|
||||||
if (FileObject->RelatedFileObject)
|
if (FileObject->RelatedFileObject)
|
||||||
{
|
{
|
||||||
|
DPRINT ("Converting relative filename to absolute filename\n");
|
||||||
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
|
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
|
||||||
FileName,
|
FileName,
|
||||||
&AbsFileName);
|
&AbsFileName);
|
||||||
FileName = AbsFileName;
|
FileName = AbsFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
|
||||||
* try first to find an existing FCB in memory
|
|
||||||
*/
|
|
||||||
CHECKPOINT;
|
|
||||||
|
|
||||||
|
DPRINT ("PathName to open: %S\n", FileName);
|
||||||
|
|
||||||
|
/* try first to find an existing FCB in memory */
|
||||||
|
DPRINT ("Checking for existing FCB in memory\n");
|
||||||
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
|
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
|
||||||
if (Fcb != NULL)
|
if (Fcb == NULL)
|
||||||
{
|
{
|
||||||
FileObject->FsContext = (PVOID)&Fcb->RFCB;
|
DPRINT ("No existing FCB found, making a new one if file exists.\n");
|
||||||
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
|
Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
|
||||||
memset (newCCB, 0, sizeof (VFATCCB));
|
|
||||||
FileObject->Flags = FileObject->Flags |
|
|
||||||
FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
|
|
||||||
FileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
|
|
||||||
FileObject->FsContext2 = newCCB;
|
|
||||||
newCCB->pFcb = Fcb;
|
|
||||||
newCCB->PtrFileObject = FileObject;
|
|
||||||
if (AbsFileName)
|
|
||||||
ExFreePool (AbsFileName);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT ("FileName %S\n", FileName);
|
|
||||||
|
|
||||||
string = FileName;
|
|
||||||
ParentFcb = NULL;
|
|
||||||
Fcb = vfatNewFCB (L"\\");
|
|
||||||
next = &string[0];
|
|
||||||
|
|
||||||
CHECKPOINT;
|
|
||||||
if (*next == 0 || *(next+1) == 0) // root
|
|
||||||
{
|
|
||||||
memset (Fcb->entry.Filename, ' ', 11);
|
|
||||||
Fcb->entry.FileSize = DeviceExt->rootDirectorySectors * BLOCKSIZE;
|
|
||||||
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
|
||||||
if (DeviceExt->FatType == FAT32)
|
|
||||||
Fcb->entry.FirstCluster = 2;
|
|
||||||
else
|
|
||||||
Fcb->entry.FirstCluster = 1;
|
|
||||||
/* FIXME : is 1 the good value for mark root? */
|
|
||||||
ParentFcb = Fcb;
|
|
||||||
DPRINT("%S filename, PathName: %S\n",FileName, ParentFcb->PathName);
|
|
||||||
Fcb = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
*next = '\\';
|
|
||||||
current = next + 1;
|
|
||||||
next = wcschr (next + 1, '\\');
|
|
||||||
if (next != NULL)
|
|
||||||
{
|
|
||||||
*next = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* reached the last path component */
|
|
||||||
DPRINT ("exiting: current '%S'\n", current);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT ("search for (%S) in (%S)\n", current, ParentFcb ? ParentFcb->PathName : L"");
|
|
||||||
Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
|
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
if (Fcb != NULL)
|
|
||||||
ExFreePool (Fcb);
|
|
||||||
if (ParentFcb != NULL)
|
if (ParentFcb != NULL)
|
||||||
ExFreePool (ParentFcb);
|
{
|
||||||
|
vfatReleaseFCB (DeviceExt, ParentFcb);
|
||||||
|
}
|
||||||
|
if (!NT_SUCCESS (Status))
|
||||||
|
{
|
||||||
|
DPRINT ("Could not make a new FCB, status: %x\n", Status);
|
||||||
|
|
||||||
if (AbsFileName)
|
if (AbsFileName)
|
||||||
ExFreePool (AbsFileName);
|
ExFreePool (AbsFileName);
|
||||||
|
|
||||||
DPRINT ("error STATUS_OBJECT_PATH_NOT_FOUND\n");
|
return Status;
|
||||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
Temp = Fcb;
|
|
||||||
CHECKPOINT;
|
|
||||||
if (ParentFcb == NULL)
|
|
||||||
{
|
|
||||||
CHECKPOINT;
|
|
||||||
Fcb = vfatNewFCB (L"\\");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Fcb = ParentFcb;
|
|
||||||
|
|
||||||
if (*(Temp->ObjectName))
|
|
||||||
{
|
|
||||||
vfat_wcsncpy(Fcb->PathName+(Fcb->ObjectName-Fcb->PathName),Temp->PathName+(Fcb->ObjectName-Fcb->PathName), MAX_PATH);
|
|
||||||
|
|
||||||
Fcb->ObjectName = &Fcb->PathName[wcslen(Fcb->PathName)];
|
|
||||||
Fcb->ObjectName[0]='\\';
|
|
||||||
Fcb->ObjectName=&Fcb->ObjectName[1];
|
|
||||||
Fcb->ObjectName[0]=0;
|
|
||||||
}
|
|
||||||
CHECKPOINT;
|
|
||||||
ParentFcb = Temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( *current != L'\0' ){ //the file name is directory. there will be no last part.
|
DPRINT ("Attaching FCB to fileObject\n");
|
||||||
/* searching for last path component */
|
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
|
||||||
DPRINT ("search for (%S) in (%S)\n", current, Fcb ? Fcb->PathName : L"");
|
|
||||||
Status = FindFile (DeviceExt, Fcb, ParentFcb, current, NULL, NULL);
|
|
||||||
if (Status != STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
/* file does not exist */
|
|
||||||
CHECKPOINT;
|
|
||||||
if (Fcb != NULL)
|
|
||||||
ExFreePool (Fcb);
|
|
||||||
if (ParentFcb != NULL)
|
|
||||||
ExFreePool (ParentFcb);
|
|
||||||
if (AbsFileName)
|
if (AbsFileName)
|
||||||
ExFreePool (AbsFileName);
|
ExFreePool (AbsFileName);
|
||||||
|
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
return Status;
|
||||||
}
|
|
||||||
|
|
||||||
Temp = Fcb;
|
|
||||||
|
|
||||||
Fcb = ParentFcb;
|
|
||||||
ParentFcb = Temp;
|
|
||||||
ParentFcb->ObjectName = &(wcschr (ParentFcb->ObjectName, '\\'))[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileObject->Flags = FileObject->Flags |
|
|
||||||
FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
|
|
||||||
FileObject->SectionObjectPointers = &ParentFcb->SectionObjectPointers;
|
|
||||||
memset(FileObject->SectionObjectPointers, 0,
|
|
||||||
sizeof(SECTION_OBJECT_POINTERS));
|
|
||||||
FileObject->FsContext = (PVOID)&ParentFcb->RFCB;
|
|
||||||
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
|
|
||||||
memset (newCCB, 0, sizeof (VFATCCB));
|
|
||||||
FileObject->FsContext2 = newCCB;
|
|
||||||
newCCB->pFcb = ParentFcb;
|
|
||||||
newCCB->PtrFileObject = FileObject;
|
|
||||||
ParentFcb->RefCount++;
|
|
||||||
ParentFcb->pDevExt = DeviceExt;
|
|
||||||
/* FIXME : initialize all fields in FCB and CCB */
|
|
||||||
|
|
||||||
BytesPerCluster = DeviceExt->Boot->SectorsPerCluster * BLOCKSIZE;
|
|
||||||
FileCacheQuantum = (BytesPerCluster >= PAGESIZE) ? BytesPerCluster : PAGESIZE;
|
|
||||||
Status = CcRosInitializeFileCache(FileObject,
|
|
||||||
&ParentFcb->RFCB.Bcb,
|
|
||||||
FileCacheQuantum);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DbgPrint("CcRosInitializeFileCache failed\n");
|
|
||||||
KeBugCheck(0);
|
|
||||||
}
|
|
||||||
DPRINT ("file open, fcb=%x\n", ParentFcb);
|
|
||||||
DPRINT ("FileSize %d\n", ParentFcb->entry.FileSize);
|
|
||||||
|
|
||||||
vfatAddFCBToTable (DeviceExt, ParentFcb);
|
|
||||||
|
|
||||||
if (Fcb)
|
|
||||||
ExFreePool (Fcb);
|
|
||||||
if (AbsFileName)
|
|
||||||
ExFreePool (AbsFileName);
|
|
||||||
CHECKPOINT;
|
|
||||||
|
|
||||||
return (STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -375,3 +375,5 @@ VfatDirectoryControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||||
return RC;
|
return RC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
227
reactos/drivers/fs/vfat/direntry.c
Normal file
227
reactos/drivers/fs/vfat/direntry.c
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
/* $Id: direntry.c,v 1.1 2001/07/05 01:51:52 rex Exp $
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#define ENTRIES_PER_PAGE(pDeviceExt) (ENTRIES_PER_SECTOR * \
|
||||||
|
(PAGESIZE / ((pDeviceExt)->BytesPerSector)))
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PFAT_DIR_ENTRY pFatDirEntry)
|
||||||
|
{
|
||||||
|
ULONG cluster;
|
||||||
|
|
||||||
|
if (pDeviceExt->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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
ULONG indexInPage = *pDirectoryIndex % ENTRIES_PER_PAGE(pDeviceExt);
|
||||||
|
ULONG pageNumber = *pDirectoryIndex / ENTRIES_PER_PAGE(pDeviceExt);
|
||||||
|
PVOID currentPage = NULL;
|
||||||
|
PCACHE_SEGMENT cacheSegment = NULL;
|
||||||
|
FATDirEntry * fatDirEntry;
|
||||||
|
slot * longNameEntry;
|
||||||
|
ULONG cpos;
|
||||||
|
|
||||||
|
DPRINT ("vfatGetNextDirEntry (%x,%x,%d,%x,%x)\n",
|
||||||
|
pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
*pDirectoryIndex,
|
||||||
|
pLongFileName,
|
||||||
|
pDirEntry);
|
||||||
|
|
||||||
|
*pLongFileName = 0;
|
||||||
|
|
||||||
|
DPRINT ("Validating current directory page\n");
|
||||||
|
status = vfatRequestAndValidateRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
pageNumber * PAGESIZE,
|
||||||
|
(PVOID *) ¤tPage,
|
||||||
|
&cacheSegment,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
fatDirEntry = (FATDirEntry *) currentPage;
|
||||||
|
|
||||||
|
if (vfatIsDirEntryEndMarker (&fatDirEntry [indexInPage]))
|
||||||
|
{
|
||||||
|
DPRINT ("end of directory, returning no more entries\n");
|
||||||
|
status = vfatReleaseRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
cacheSegment);
|
||||||
|
return STATUS_NO_MORE_ENTRIES;
|
||||||
|
}
|
||||||
|
else if (vfatIsDirEntryLongName (&fatDirEntry [indexInPage]))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
while ((longNameEntry [indexInPage].id != 0x41) &&
|
||||||
|
(longNameEntry [indexInPage].id != 0x01) &&
|
||||||
|
(longNameEntry [indexInPage].attr > 0))
|
||||||
|
{
|
||||||
|
(*pDirectoryIndex)++;
|
||||||
|
indexInPage++;
|
||||||
|
if (indexInPage == ENTRIES_PER_PAGE(pDeviceExt))
|
||||||
|
{
|
||||||
|
indexInPage = 0;
|
||||||
|
pageNumber++;
|
||||||
|
|
||||||
|
status = vfatReleaseRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
cacheSegment);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = vfatRequestAndValidateRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
pageNumber * PAGESIZE,
|
||||||
|
(PVOID *) ¤tPage,
|
||||||
|
&cacheSegment,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
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++;
|
||||||
|
if (indexInPage == ENTRIES_PER_PAGE(pDeviceExt))
|
||||||
|
{
|
||||||
|
indexInPage = 0;
|
||||||
|
pageNumber++;
|
||||||
|
|
||||||
|
status = vfatReleaseRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
cacheSegment);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = vfatRequestAndValidateRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
pageNumber * PAGESIZE,
|
||||||
|
(PVOID *) ¤tPage,
|
||||||
|
&cacheSegment,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (pDirEntry, &fatDirEntry [indexInPage], sizeof (FAT_DIR_ENTRY));
|
||||||
|
(*pDirectoryIndex)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT ("Releasing current directory page\n");
|
||||||
|
status = vfatReleaseRegion (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
cacheSegment);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: fcb.c,v 1.3 2001/05/10 06:30:23 rex Exp $
|
/* $Id: fcb.c,v 1.4 2001/07/05 01:51:52 rex Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* FILE: fcb.c
|
* FILE: fcb.c
|
||||||
|
@ -54,10 +54,27 @@ void vfatDestroyFCB (PVFATFCB pFCB)
|
||||||
ExFreePool (pFCB);
|
ExFreePool (pFCB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB)
|
||||||
|
{
|
||||||
|
return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
vfatFCBIsRoot (PVFATFCB FCB)
|
||||||
|
{
|
||||||
|
return wcscmp (FCB->PathName, L"\\") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void vfatGrabFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
void vfatGrabFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
DPRINT ("grabbing FCB at %x: %S, refCount:%d\n",
|
||||||
|
pFCB,
|
||||||
|
pFCB->PathName,
|
||||||
|
pFCB->RefCount);
|
||||||
|
|
||||||
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
||||||
pFCB->RefCount++;
|
pFCB->RefCount++;
|
||||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||||
|
@ -67,6 +84,11 @@ void vfatReleaseFCB (PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
DPRINT ("releasing FCB at %x: %S, refCount:%d\n",
|
||||||
|
pFCB,
|
||||||
|
pFCB->PathName,
|
||||||
|
pFCB->RefCount);
|
||||||
|
|
||||||
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
||||||
pFCB->RefCount--;
|
pFCB->RefCount--;
|
||||||
if (pFCB->RefCount <= 0 && !vfatFCBIsDirectory (pVCB, pFCB))
|
if (pFCB->RefCount <= 0 && !vfatFCBIsDirectory (pVCB, pFCB))
|
||||||
|
@ -95,39 +117,168 @@ vfatGrabFCBFromTable (PDEVICE_EXTENSION pVCB, PWSTR pFileName)
|
||||||
PVFATFCB rcFCB;
|
PVFATFCB rcFCB;
|
||||||
PLIST_ENTRY current_entry;
|
PLIST_ENTRY current_entry;
|
||||||
|
|
||||||
CHECKPOINT;
|
|
||||||
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
|
||||||
CHECKPOINT;
|
|
||||||
current_entry = pVCB->FcbListHead.Flink;
|
current_entry = pVCB->FcbListHead.Flink;
|
||||||
while (current_entry != &pVCB->FcbListHead)
|
while (current_entry != &pVCB->FcbListHead)
|
||||||
{
|
{
|
||||||
rcFCB = CONTAINING_RECORD (current_entry, VFATFCB, FcbListEntry);
|
rcFCB = CONTAINING_RECORD (current_entry, VFATFCB, FcbListEntry);
|
||||||
|
|
||||||
DPRINT ("Next FCB in list at %x\n", rcFCB);
|
|
||||||
DPRINT (" PathName:%S\n", rcFCB->PathName);
|
|
||||||
|
|
||||||
if (wstrcmpi (pFileName, rcFCB->PathName))
|
if (wstrcmpi (pFileName, rcFCB->PathName))
|
||||||
{
|
{
|
||||||
rcFCB->RefCount++;
|
rcFCB->RefCount++;
|
||||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||||
return rcFCB;
|
return rcFCB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIXME: need to compare against short name in FCB here
|
||||||
|
|
||||||
current_entry = current_entry->Flink;
|
current_entry = current_entry->Flink;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
|
||||||
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVFATFCB
|
NTSTATUS
|
||||||
vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
|
vfatFCBInitializeCache (PVCB vcb, PVFATFCB fcb)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
PVFATFCB FCB;
|
|
||||||
PFILE_OBJECT fileObject;
|
PFILE_OBJECT fileObject;
|
||||||
ULONG bytesPerCluster;
|
ULONG bytesPerCluster;
|
||||||
ULONG fileCacheQuantum;
|
ULONG fileCacheQuantum;
|
||||||
|
PVFATCCB newCCB;
|
||||||
|
|
||||||
|
fileObject = IoCreateStreamFileObject (NULL, vcb->StorageDevice);
|
||||||
|
|
||||||
|
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
|
||||||
|
if (newCCB == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
memset (newCCB, 0, sizeof (VFATCCB));
|
||||||
|
|
||||||
|
fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID |
|
||||||
|
FO_DIRECT_CACHE_PAGING_READ;
|
||||||
|
fileObject->SectionObjectPointers = &fcb->SectionObjectPointers;
|
||||||
|
fileObject->FsContext = (PVOID) &fcb->RFCB;
|
||||||
|
fileObject->FsContext2 = newCCB;
|
||||||
|
newCCB->pFcb = fcb;
|
||||||
|
newCCB->PtrFileObject = fileObject;
|
||||||
|
fcb->pDevExt = vcb;
|
||||||
|
|
||||||
|
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
|
||||||
|
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ?
|
||||||
|
bytesPerCluster : PAGESIZE;
|
||||||
|
status = CcRosInitializeFileCache (fileObject,
|
||||||
|
&fcb->RFCB.Bcb,
|
||||||
|
fileCacheQuantum);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
DbgPrint ("CcRosInitializeFileCache failed\n");
|
||||||
|
KeBugCheck (0);
|
||||||
|
}
|
||||||
|
ObDereferenceObject (fileObject);
|
||||||
|
fcb->isCacheInitialized = TRUE;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
vfatRequestAndValidateRegion (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pFCB,
|
||||||
|
ULONG pOffset,
|
||||||
|
PVOID * pBuffer,
|
||||||
|
PCACHE_SEGMENT * pCacheSegment,
|
||||||
|
BOOL pExtend)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
BOOLEAN valid;
|
||||||
|
BOOLEAN isRoot;
|
||||||
|
ULONG currentCluster;
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
status = CcRosRequestCacheSegment(pFCB->RFCB.Bcb,
|
||||||
|
pOffset,
|
||||||
|
pBuffer,
|
||||||
|
&valid,
|
||||||
|
pCacheSegment);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
isRoot = vfatFCBIsRoot (pFCB);
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
currentCluster = vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry);
|
||||||
|
status = OffsetToCluster (pDeviceExt,
|
||||||
|
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
|
||||||
|
pOffset,
|
||||||
|
¤tCluster,
|
||||||
|
pExtend);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PAGESIZE > pDeviceExt->BytesPerCluster)
|
||||||
|
{
|
||||||
|
for (i = 0; i < (PAGESIZE / pDeviceExt->BytesPerCluster); i++)
|
||||||
|
{
|
||||||
|
status = VfatRawReadCluster (pDeviceExt,
|
||||||
|
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
|
||||||
|
((PCHAR)*pBuffer) +
|
||||||
|
(i * pDeviceExt->BytesPerCluster),
|
||||||
|
currentCluster);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = NextCluster (pDeviceExt,
|
||||||
|
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
|
||||||
|
¤tCluster,
|
||||||
|
pExtend);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if ((currentCluster) == 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = VfatRawReadCluster (pDeviceExt,
|
||||||
|
vfatDirEntryGetFirstCluster (pDeviceExt, &pFCB->entry),
|
||||||
|
*pBuffer,
|
||||||
|
currentCluster);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
CcRosReleaseCacheSegment(pFCB->RFCB.Bcb, *pCacheSegment, FALSE);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
vfatReleaseRegion (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pFCB,
|
||||||
|
PCACHE_SEGMENT pCacheSegment)
|
||||||
|
{
|
||||||
|
return CcRosReleaseCacheSegment (pFCB->RFCB.Bcb, pCacheSegment, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVFATFCB
|
||||||
|
vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
|
||||||
|
{
|
||||||
|
PVFATFCB FCB;
|
||||||
|
|
||||||
FCB = vfatNewFCB (L"\\");
|
FCB = vfatNewFCB (L"\\");
|
||||||
memset (FCB->entry.Filename, ' ', 11);
|
memset (FCB->entry.Filename, ' ', 11);
|
||||||
|
@ -142,21 +293,10 @@ vfatMakeRootFCB (PDEVICE_EXTENSION pVCB)
|
||||||
FCB->entry.FirstCluster = 1;
|
FCB->entry.FirstCluster = 1;
|
||||||
}
|
}
|
||||||
FCB->RefCount = 1;
|
FCB->RefCount = 1;
|
||||||
fileObject = IoCreateStreamFileObject (NULL, pVCB->StorageDevice);
|
|
||||||
|
|
||||||
bytesPerCluster = pVCB->Boot->SectorsPerCluster * BLOCKSIZE;
|
vfatFCBInitializeCache (pVCB, FCB);
|
||||||
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ?
|
|
||||||
bytesPerCluster : PAGESIZE;
|
|
||||||
status = CcRosInitializeFileCache (fileObject,
|
|
||||||
&FCB->RFCB.Bcb,
|
|
||||||
fileCacheQuantum);
|
|
||||||
if (!NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
DbgPrint ("CcRosInitializeFileCache failed\n");
|
|
||||||
KeBugCheck (0);
|
|
||||||
}
|
|
||||||
ObDereferenceObject (fileObject);
|
|
||||||
vfatAddFCBToTable (pVCB, FCB);
|
vfatAddFCBToTable (pVCB, FCB);
|
||||||
|
vfatGrabFCB(pVCB, FCB);
|
||||||
|
|
||||||
return FCB;
|
return FCB;
|
||||||
}
|
}
|
||||||
|
@ -167,27 +307,191 @@ vfatOpenRootFCB (PDEVICE_EXTENSION pVCB)
|
||||||
PVFATFCB FCB;
|
PVFATFCB FCB;
|
||||||
|
|
||||||
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
|
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
|
||||||
if (FCB != NULL)
|
if (FCB == NULL)
|
||||||
{
|
{
|
||||||
return FCB;
|
|
||||||
}
|
|
||||||
FCB = vfatMakeRootFCB (pVCB);
|
FCB = vfatMakeRootFCB (pVCB);
|
||||||
|
}
|
||||||
|
|
||||||
return FCB;
|
return FCB;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
NTSTATUS
|
||||||
vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB)
|
vfatMakeFCBFromDirEntry (PVCB vcb,
|
||||||
|
PVFATFCB directoryFCB,
|
||||||
|
PWSTR longName,
|
||||||
|
PFAT_DIR_ENTRY dirEntry,
|
||||||
|
PVFATFCB * fileFCB)
|
||||||
{
|
{
|
||||||
return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY;
|
PVFATFCB rcFCB;
|
||||||
|
WCHAR pathName [MAX_PATH];
|
||||||
|
|
||||||
|
if (longName [0] != 0 && wcslen (directoryFCB->PathName) +
|
||||||
|
sizeof(WCHAR) + wcslen (longName) > MAX_PATH)
|
||||||
|
{
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
}
|
||||||
|
wcscpy (pathName, directoryFCB->PathName);
|
||||||
|
if (!vfatFCBIsRoot (directoryFCB))
|
||||||
|
{
|
||||||
|
wcscat (pathName, L"\\");
|
||||||
|
}
|
||||||
|
if (longName [0] != 0)
|
||||||
|
{
|
||||||
|
wcscat (pathName, longName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WCHAR entryName [MAX_PATH];
|
||||||
|
|
||||||
|
vfatGetDirEntryName (dirEntry, entryName);
|
||||||
|
wcscat (pathName, entryName);
|
||||||
|
}
|
||||||
|
rcFCB = vfatNewFCB (pathName);
|
||||||
|
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY));
|
||||||
|
|
||||||
|
vfatFCBInitializeCache (vcb, rcFCB);
|
||||||
|
vfatAddFCBToTable (vcb, rcFCB);
|
||||||
|
vfatGrabFCB (vcb, rcFCB);
|
||||||
|
*fileFCB = rcFCB;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVFATFCB
|
NTSTATUS
|
||||||
vfatDirFindFile (PDEVICE_EXTENSION pVCB,
|
vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
||||||
PVFATFCB parentFCB,
|
PVFATFCB fcb,
|
||||||
const PWSTR elementName)
|
PFILE_OBJECT fileObject)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
NTSTATUS status;
|
||||||
|
PVFATCCB newCCB;
|
||||||
|
|
||||||
|
newCCB = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
|
||||||
|
if (newCCB == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
memset (newCCB, 0, sizeof (VFATCCB));
|
||||||
|
|
||||||
|
fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID |
|
||||||
|
FO_DIRECT_CACHE_PAGING_READ;
|
||||||
|
fileObject->SectionObjectPointers = &fcb->SectionObjectPointers;
|
||||||
|
fileObject->FsContext = (PVOID) &fcb->RFCB;
|
||||||
|
fileObject->FsContext2 = newCCB;
|
||||||
|
newCCB->pFcb = fcb;
|
||||||
|
newCCB->PtrFileObject = fileObject;
|
||||||
|
fcb->pDevExt = vcb;
|
||||||
|
|
||||||
|
if (!fcb->isCacheInitialized)
|
||||||
|
{
|
||||||
|
ULONG bytesPerCluster;
|
||||||
|
ULONG fileCacheQuantum;
|
||||||
|
|
||||||
|
bytesPerCluster = vcb->Boot->SectorsPerCluster * BLOCKSIZE;
|
||||||
|
fileCacheQuantum = (bytesPerCluster >= PAGESIZE) ? bytesPerCluster :
|
||||||
|
PAGESIZE;
|
||||||
|
status = CcRosInitializeFileCache (fileObject,
|
||||||
|
&fcb->RFCB.Bcb,
|
||||||
|
fileCacheQuantum);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
DbgPrint ("CcRosInitializeFileCache failed\n");
|
||||||
|
KeBugCheck (0);
|
||||||
|
}
|
||||||
|
fcb->isCacheInitialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pDirectoryFCB,
|
||||||
|
PWSTR pFileToFind,
|
||||||
|
PVFATFCB * pFoundFCB)
|
||||||
|
{
|
||||||
|
BOOL finishedScanningDirectory;
|
||||||
|
ULONG directoryIndex;
|
||||||
|
NTSTATUS status;
|
||||||
|
WCHAR defaultFileName [2];
|
||||||
|
WCHAR currentLongName [256];
|
||||||
|
FAT_DIR_ENTRY currentDirEntry;
|
||||||
|
WCHAR currentEntryName [256];
|
||||||
|
|
||||||
|
assert (pDeviceExt);
|
||||||
|
assert (pDirectoryFCB);
|
||||||
|
assert (pFileToFind);
|
||||||
|
|
||||||
|
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n",
|
||||||
|
pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
pFileToFind);
|
||||||
|
DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName);
|
||||||
|
|
||||||
|
// default to '.' if no filename specified
|
||||||
|
if (wcslen (pFileToFind) == 0)
|
||||||
|
{
|
||||||
|
defaultFileName [0] = L'.';
|
||||||
|
defaultFileName [1] = 0;
|
||||||
|
pFileToFind = defaultFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
directoryIndex = 0;
|
||||||
|
finishedScanningDirectory = FALSE;
|
||||||
|
while (!finishedScanningDirectory)
|
||||||
|
{
|
||||||
|
status = vfatGetNextDirEntry (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
&directoryIndex,
|
||||||
|
currentLongName,
|
||||||
|
¤tDirEntry);
|
||||||
|
if (status == STATUS_NO_MORE_ENTRIES)
|
||||||
|
{
|
||||||
|
finishedScanningDirectory = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT (" Index:%d longName:%S\n",
|
||||||
|
directoryIndex,
|
||||||
|
currentLongName);
|
||||||
|
|
||||||
|
if (!vfatIsDirEntryDeleted (¤tDirEntry))
|
||||||
|
{
|
||||||
|
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
|
||||||
|
{
|
||||||
|
DPRINT ("Match found, %S\n", currentLongName);
|
||||||
|
status = vfatMakeFCBFromDirEntry (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
currentLongName,
|
||||||
|
¤tDirEntry,
|
||||||
|
pFoundFCB);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vfatGetDirEntryName (¤tDirEntry, currentEntryName);
|
||||||
|
DPRINT (" entryName:%S\n", currentEntryName);
|
||||||
|
|
||||||
|
if (wstrcmpjoki (currentEntryName, pFileToFind))
|
||||||
|
{
|
||||||
|
DPRINT ("Match found, %S\n", currentEntryName);
|
||||||
|
status = vfatMakeFCBFromDirEntry (pDeviceExt,
|
||||||
|
pDirectoryFCB,
|
||||||
|
currentLongName,
|
||||||
|
¤tDirEntry,
|
||||||
|
pFoundFCB);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -196,27 +500,30 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB *pFCB,
|
PVFATFCB *pFCB,
|
||||||
const PWSTR pFileName)
|
const PWSTR pFileName)
|
||||||
{
|
{
|
||||||
|
NTSTATUS status;
|
||||||
WCHAR pathName [MAX_PATH];
|
WCHAR pathName [MAX_PATH];
|
||||||
WCHAR elementName [MAX_PATH];
|
WCHAR elementName [MAX_PATH];
|
||||||
PWCHAR currentElement;
|
PWCHAR currentElement;
|
||||||
PVFATFCB FCB;
|
PVFATFCB FCB;
|
||||||
PVFATFCB parentFCB;
|
PVFATFCB parentFCB;
|
||||||
|
|
||||||
|
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%S)\n",
|
||||||
|
pVCB,
|
||||||
|
pParentFCB,
|
||||||
|
pFCB,
|
||||||
|
pFileName);
|
||||||
|
|
||||||
// Trivial case, open of the root directory on volume
|
// Trivial case, open of the root directory on volume
|
||||||
if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0)
|
if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0)
|
||||||
{
|
{
|
||||||
currentElement = pFileName;
|
DPRINT ("returning root FCB\n");
|
||||||
//FIXME: grab/create root RCB and return it
|
|
||||||
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
|
FCB = vfatOpenRootFCB (pVCB);
|
||||||
if (FCB == NULL)
|
|
||||||
{
|
|
||||||
FCB = vfatMakeRootFCB (pVCB);
|
|
||||||
*pFCB = FCB;
|
*pFCB = FCB;
|
||||||
*pParentFCB = NULL;
|
*pParentFCB = NULL;
|
||||||
|
|
||||||
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
|
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentElement = pFileName + 1;
|
currentElement = pFileName + 1;
|
||||||
|
@ -235,7 +542,8 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentElement = vfatGetNextPathElement (currentElement);
|
DPRINT ("Parsing, currentElement:%S\n", currentElement);
|
||||||
|
DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB);
|
||||||
|
|
||||||
// descend to next directory level
|
// descend to next directory level
|
||||||
if (parentFCB)
|
if (parentFCB)
|
||||||
|
@ -246,8 +554,13 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
// fail if element in FCB is not a directory
|
// fail if element in FCB is not a directory
|
||||||
if (!vfatFCBIsDirectory (pVCB, FCB))
|
if (!vfatFCBIsDirectory (pVCB, FCB))
|
||||||
{
|
{
|
||||||
|
DPRINT ("Element in requested path is not a directory\n");
|
||||||
|
|
||||||
vfatReleaseFCB (pVCB, FCB);
|
vfatReleaseFCB (pVCB, FCB);
|
||||||
FCB = 0;
|
FCB = 0;
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
*pFCB = NULL;
|
||||||
|
|
||||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
parentFCB = FCB;
|
parentFCB = FCB;
|
||||||
|
@ -256,6 +569,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
vfatWSubString (pathName,
|
vfatWSubString (pathName,
|
||||||
pFileName,
|
pFileName,
|
||||||
vfatGetNextPathElement (currentElement) - pFileName);
|
vfatGetNextPathElement (currentElement) - pFileName);
|
||||||
|
DPRINT (" pathName:%S\n", pathName);
|
||||||
|
|
||||||
FCB = vfatGrabFCBFromTable (pVCB, pathName);
|
FCB = vfatGrabFCBFromTable (pVCB, pathName);
|
||||||
if (FCB == NULL)
|
if (FCB == NULL)
|
||||||
|
@ -263,12 +577,14 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
vfatWSubString (elementName,
|
vfatWSubString (elementName,
|
||||||
currentElement,
|
currentElement,
|
||||||
vfatGetNextPathElement (currentElement) - currentElement);
|
vfatGetNextPathElement (currentElement) - currentElement);
|
||||||
FCB = vfatDirFindFile (pVCB, parentFCB, elementName);
|
DPRINT (" elementName:%S\n", elementName);
|
||||||
if (FCB == NULL)
|
|
||||||
|
status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB);
|
||||||
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||||
{
|
{
|
||||||
*pParentFCB = parentFCB;
|
*pParentFCB = parentFCB;
|
||||||
*pFCB = NULL;
|
*pFCB = NULL;
|
||||||
if (vfatGetNextPathElement (currentElement) == 0)
|
if (vfatGetNextPathElement (vfatGetNextPathElement (currentElement) + 1) == 0)
|
||||||
{
|
{
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -277,10 +593,17 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
return STATUS_OBJECT_PATH_NOT_FOUND;
|
return STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
vfatReleaseFCB (pVCB, parentFCB);
|
||||||
|
*pParentFCB = NULL;
|
||||||
|
*pFCB = NULL;
|
||||||
|
|
||||||
// FIXME: check security on directory element and fail if access denied
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
currentElement = vfatGetNextPathElement (currentElement);
|
||||||
|
}
|
||||||
|
|
||||||
*pParentFCB = parentFCB;
|
*pParentFCB = parentFCB;
|
||||||
*pFCB = FCB;
|
*pFCB = FCB;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: iface.c,v 1.53 2001/06/11 19:52:22 ekohl Exp $
|
/* $Id: iface.c,v 1.54 2001/07/05 01:51:52 rex Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -103,6 +103,7 @@ VfatMountDevice (PDEVICE_EXTENSION DeviceExt, PDEVICE_OBJECT DeviceToMount)
|
||||||
DeviceExt->Boot->FATCount * DeviceExt->Boot->FATSectors;
|
DeviceExt->Boot->FATCount * DeviceExt->Boot->FATSectors;
|
||||||
DeviceExt->dataStart =
|
DeviceExt->dataStart =
|
||||||
DeviceExt->rootStart + DeviceExt->rootDirectorySectors;
|
DeviceExt->rootStart + DeviceExt->rootDirectorySectors;
|
||||||
|
DeviceExt->BytesPerSector = DeviceExt->Boot->BytesPerSector;
|
||||||
DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32;
|
DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32;
|
||||||
DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
|
DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
|
||||||
DeviceExt->Boot->BytesPerSector;
|
DeviceExt->Boot->BytesPerSector;
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# $Id: makefile,v 1.31 2001/06/22 12:27:48 ekohl Exp $
|
# $Id: makefile,v 1.32 2001/07/05 01:51:52 rex Exp $
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
PATH_TO_TOP = ../../..
|
PATH_TO_TOP = ../../..
|
||||||
|
|
||||||
TARGET=vfatfs
|
TARGET=vfatfs
|
||||||
|
|
||||||
OBJECTS = blockdev.o close.o create.o dir.o dirwr.o iface.o string.o fat.o \
|
OBJECTS = blockdev.o cleanup.o close.o create.o dir.o direntry.o dirwr.o \
|
||||||
rw.o finfo.o volume.o shutdown.o cleanup.o fcb.o $(TARGET).coff
|
fat.o fcb.o finfo.o iface.o rw.o shutdown.o string.o volume.o \
|
||||||
|
$(TARGET).coff
|
||||||
|
|
||||||
LIBS = $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.a
|
LIBS = $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.a
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: string.c,v 1.7 2001/05/10 04:02:21 rex Exp $
|
/* $Id: string.c,v 1.8 2001/07/05 01:51:53 rex Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -151,7 +151,7 @@ BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
|
||||||
PWCHAR
|
PWCHAR
|
||||||
vfatGetNextPathElement (PWCHAR pFileName)
|
vfatGetNextPathElement (PWCHAR pFileName)
|
||||||
{
|
{
|
||||||
if (*pFileName != L'\0')
|
if (*pFileName == L'\0')
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: vfat.h,v 1.31 2001/06/14 10:02:59 ekohl Exp $ */
|
/* $Id: vfat.h,v 1.32 2001/07/05 01:51:53 rex Exp $ */
|
||||||
|
|
||||||
#include <ddk/ntifs.h>
|
#include <ddk/ntifs.h>
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ struct _FATDirEntry {
|
||||||
unsigned long FileSize;
|
unsigned long FileSize;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
typedef struct _FATDirEntry FATDirEntry;
|
typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
|
||||||
|
|
||||||
struct _slot
|
struct _slot
|
||||||
{
|
{
|
||||||
|
@ -87,10 +87,11 @@ typedef struct
|
||||||
PBCB Fat12StorageBcb;
|
PBCB Fat12StorageBcb;
|
||||||
BootSector *Boot;
|
BootSector *Boot;
|
||||||
int rootDirectorySectors, FATStart, rootStart, dataStart;
|
int rootDirectorySectors, FATStart, rootStart, dataStart;
|
||||||
|
int BytesPerSector;
|
||||||
int FATEntriesPerSector, FATUnit;
|
int FATEntriesPerSector, FATUnit;
|
||||||
ULONG BytesPerCluster;
|
ULONG BytesPerCluster;
|
||||||
ULONG FatType;
|
ULONG FatType;
|
||||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
|
||||||
|
|
||||||
typedef struct _VFATFCB
|
typedef struct _VFATFCB
|
||||||
{
|
{
|
||||||
|
@ -105,6 +106,7 @@ typedef struct _VFATFCB
|
||||||
PDEVICE_EXTENSION pDevExt;
|
PDEVICE_EXTENSION pDevExt;
|
||||||
LIST_ENTRY FcbListEntry;
|
LIST_ENTRY FcbListEntry;
|
||||||
struct _VFATFCB* parentFcb;
|
struct _VFATFCB* parentFcb;
|
||||||
|
BOOL isCacheInitialized;
|
||||||
} VFATFCB, *PVFATFCB;
|
} VFATFCB, *PVFATFCB;
|
||||||
|
|
||||||
typedef struct _VFATCCB
|
typedef struct _VFATCCB
|
||||||
|
@ -120,6 +122,9 @@ typedef struct _VFATCCB
|
||||||
// PSTRING DirectorySearchPattern;// for DirectoryControl ?
|
// PSTRING DirectorySearchPattern;// for DirectoryControl ?
|
||||||
} VFATCCB, *PVFATCCB;
|
} VFATCCB, *PVFATCCB;
|
||||||
|
|
||||||
|
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
|
||||||
|
|
||||||
|
#define TAG_CCB TAG('V', 'C', 'C', 'B')
|
||||||
|
|
||||||
#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
|
#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
|
||||||
|
|
||||||
|
@ -249,6 +254,12 @@ BOOL vfatIsFileNameValid (PWCHAR pFileName);
|
||||||
/*
|
/*
|
||||||
* functions from fat.c
|
* functions from fat.c
|
||||||
*/
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
|
ULONG FirstCluster,
|
||||||
|
ULONG FileOffset,
|
||||||
|
PULONG Cluster,
|
||||||
|
BOOLEAN Extend);
|
||||||
ULONG
|
ULONG
|
||||||
ClusterToSector(PDEVICE_EXTENSION DeviceExt,
|
ClusterToSector(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG Cluster);
|
ULONG Cluster);
|
||||||
|
@ -286,9 +297,9 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
||||||
ULONG ClusterToWrite,
|
ULONG ClusterToWrite,
|
||||||
ULONG NewValue);
|
ULONG NewValue);
|
||||||
|
|
||||||
/*
|
/* --------------------------------------------------------- create.c */
|
||||||
* From create.c
|
|
||||||
*/
|
void vfat8Dot3ToString (PCHAR pBasename, PCHAR pExtension, PWSTR pName);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb);
|
ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb);
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -296,6 +307,18 @@ VfatOpenFile(PDEVICE_EXTENSION DeviceExt,
|
||||||
PFILE_OBJECT FileObject,
|
PFILE_OBJECT FileObject,
|
||||||
PWSTR FileName);
|
PWSTR FileName);
|
||||||
|
|
||||||
|
/* ----------------------------------------------- DirEntry Functions */
|
||||||
|
|
||||||
|
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PFAT_DIR_ENTRY pDirEntry);
|
||||||
|
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
|
||||||
|
void vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry, PWSTR pEntryName);
|
||||||
|
NTSTATUS vfatGetNextDirEntry (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pDirectoryFCB,
|
||||||
|
ULONG * pDirectoryIndex,
|
||||||
|
PWSTR pLongFileName,
|
||||||
|
PFAT_DIR_ENTRY pDirEntry);
|
||||||
|
|
||||||
/* ----------------------------------------------------- FCB Functions */
|
/* ----------------------------------------------------- FCB Functions */
|
||||||
|
|
||||||
PVFATFCB vfatNewFCB (PWCHAR pFileName);
|
PVFATFCB vfatNewFCB (PWCHAR pFileName);
|
||||||
|
@ -306,12 +329,25 @@ void vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB pFCB);
|
PVFATFCB pFCB);
|
||||||
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
|
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
|
||||||
PWSTR pFileName);
|
PWSTR pFileName);
|
||||||
|
NTSTATUS vfatRequestAndValidateRegion (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pFCB,
|
||||||
|
ULONG pOffset,
|
||||||
|
PVOID * pBuffer,
|
||||||
|
PCACHE_SEGMENT * pCacheSegment,
|
||||||
|
BOOL pExtend);
|
||||||
|
NTSTATUS vfatReleaseRegion (PDEVICE_EXTENSION pDeviceExt,
|
||||||
|
PVFATFCB pFCB,
|
||||||
|
PCACHE_SEGMENT pCacheSegment);
|
||||||
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
|
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
|
||||||
PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB);
|
PVFATFCB vfatOpenRootFCB (PDEVICE_EXTENSION pVCB);
|
||||||
BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB);
|
BOOL vfatFCBIsDirectory (PDEVICE_EXTENSION pVCB, PVFATFCB FCB);
|
||||||
PVFATFCB vfatDirFindFile (PDEVICE_EXTENSION pVCB,
|
NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
|
||||||
|
PVFATFCB fcb,
|
||||||
|
PFILE_OBJECT fileObject);
|
||||||
|
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB parentFCB,
|
PVFATFCB parentFCB,
|
||||||
const PWSTR elementName);
|
PWSTR elementName,
|
||||||
|
PVFATFCB * fileFCB);
|
||||||
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
|
||||||
PVFATFCB *pParentFCB,
|
PVFATFCB *pParentFCB,
|
||||||
PVFATFCB *pFCB,
|
PVFATFCB *pFCB,
|
||||||
|
|
Loading…
Reference in a new issue