- Changed the file names to unicode strings.

- Replaced most of the string functions with the unicode functions.
- Removed some overhead.
- Fixed some minor bugs.

svn path=/trunk/; revision=6279
This commit is contained in:
Hartmut Birr 2003-10-11 17:51:56 +00:00
parent a751ffce23
commit 096a69471d
21 changed files with 1510 additions and 1556 deletions

View file

@ -1,9 +1,10 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/blockdev.c
* FILE: drivers/fs/vfat/blockdev.c
* PURPOSE: Temporary sector reading support
* PROGRAMMER: David Welch (welch@cwcom.net)
* Hartmut Birr
* UPDATE HISTORY:
*/

View file

@ -1,10 +1,11 @@
/* $Id: cleanup.c,v 1.13 2003/07/24 20:52:58 chorns Exp $
/* $Id: cleanup.c,v 1.14 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/cleanup.c
* FILE: drivers/fs/vfat/cleanup.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/
/* INCLUDES *****************************************************************/
@ -25,32 +26,36 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
*/
{
PVFATFCB pFcb;
PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt;
PFILE_OBJECT FileObject = IrpContext->FileObject;
DPRINT("VfatCleanupFile(DeviceExt %x, FileObject %x)\n",
DeviceExt, FileObject);
IrpContext->DeviceExt, FileObject);
/* FIXME: handle file/directory deletion here */
pFcb = (PVFATFCB) FileObject->FsContext;
if (pFcb)
{
if (!(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) &&
FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
{
/* remove all locks this process have on this file */
FsRtlFastUnlockAll(&pFcb->FileLock,
FileObject,
IoGetRequestorProcess(IrpContext->Irp),
NULL);
}
{
if (!(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) &&
FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
{
/* remove all locks this process have on this file */
FsRtlFastUnlockAll(&pFcb->FileLock,
FileObject,
IoGetRequestorProcess(IrpContext->Irp),
NULL);
}
if (pFcb->Flags & FCB_IS_DIRTY)
{
VfatUpdateEntry (pFcb);
}
/* Uninitialize file cache if initialized for this file object. */
if (FileObject->PrivateCacheMap)
{
CcRosReleaseFileCache (FileObject);
}
}
{
CcRosReleaseFileCache (FileObject);
}
}
return STATUS_SUCCESS;
}
@ -63,17 +68,17 @@ NTSTATUS VfatCleanup (PVFAT_IRP_CONTEXT IrpContext)
DPRINT("VfatCleanup(DeviceObject %x, Irp %x)\n", IrpContext->DeviceObject, IrpContext->Irp);
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
Status = STATUS_SUCCESS;
goto ByeBye;
}
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
Status = STATUS_SUCCESS;
goto ByeBye;
}
if (!ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{
return VfatQueueRequest (IrpContext);
}
{
return VfatQueueRequest (IrpContext);
}
Status = VfatCleanupFile(IrpContext);

View file

@ -1,10 +1,11 @@
/* $Id: close.c,v 1.20 2003/07/24 20:52:58 chorns Exp $
/* $Id: close.c,v 1.21 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/close.c
* FILE: drivers/fs/vfat/close.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/
/* INCLUDES *****************************************************************/
@ -55,7 +56,7 @@ VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
{
if (pFcb->Flags & FCB_DELETE_PENDING)
{
delEntry (DeviceExt, FileObject);
VfatDelEntry (DeviceExt, pFcb);
}
else
{

View file

@ -16,13 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: create.c,v 1.63 2003/07/24 20:52:58 chorns Exp $
/* $Id: create.c,v 1.64 2003/10/11 17:51:56 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/create.c
* FILE: drivers/fs/vfat/create.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/
/* INCLUDES *****************************************************************/
@ -42,73 +42,60 @@
/* FUNCTIONS *****************************************************************/
void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PWSTR pName)
void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
{
int fromIndex, toIndex;
fromIndex = toIndex = 0;
while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
{
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
{
pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Filename [fromIndex++];
}
}
if (pEntry->Ext [0] != ' ')
{
pName [toIndex++] = L'.';
fromIndex = 0;
while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
OEM_STRING StringA;
ULONG Length;
CHAR cString[12];
memcpy(cString, pEntry->Filename, 11);
cString[11] = 0;
if (cString[0] == 0x05)
{
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
{
pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Ext [fromIndex++];
}
}
}
pName [toIndex] = L'\0';
}
cString[0] = 0xe5;
}
static void vfat8Dot3ToVolumeLabel (PFAT_DIR_ENTRY pEntry, PWSTR pName)
{
int fromIndex, toIndex;
StringA.Buffer = cString;
for (StringA.Length = 0;
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
StringA.Length++);
StringA.MaximumLength = StringA.Length;
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
fromIndex = toIndex = 0;
while (fromIndex < 8 && pEntry->Filename [fromIndex] != ' ')
{
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
{
pName [toIndex++] = tolower(pEntry->Filename [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Filename [fromIndex++];
}
}
if (pEntry->Ext [0] != ' ')
{
fromIndex = 0;
while (fromIndex < 3 && pEntry->Ext [fromIndex] != ' ')
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
{
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
{
pName [toIndex++] = tolower(pEntry->Ext [fromIndex++]);
}
else
{
pName [toIndex++] = pEntry->Ext [fromIndex++];
}
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
}
}
pName [toIndex] = L'\0';
if (cString[8] != ' ')
{
Length = NameU->Length;
NameU->Buffer += Length / sizeof(WCHAR);
if (!ENTRY_VOLUME(pEntry))
{
Length += sizeof(WCHAR);
NameU->Buffer[0] = L'.';
NameU->Buffer++;
}
NameU->Length = 0;
NameU->MaximumLength -= Length;
StringA.Buffer = &cString[8];
for (StringA.Length = 0;
StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
StringA.Length++);
StringA.MaximumLength = StringA.Length;
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
{
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
}
NameU->Buffer -= Length / sizeof(WCHAR);
NameU->Length += Length;
NameU->MaximumLength += Length;
}
NameU->Buffer[NameU->Length / sizeof(WCHAR)] = 0;
DPRINT("'%wZ'\n", NameU);
}
NTSTATUS
@ -122,25 +109,31 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
FATDirEntry* Entry;
PVFATFCB pFcb;
LARGE_INTEGER FileOffset;
UNICODE_STRING NameU;
NameU.Buffer = Vpb->VolumeLabel;
NameU.Length = 0;
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
*(Vpb->VolumeLabel) = 0;
Vpb->VolumeLabelLength = 0;
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
pFcb = vfatOpenRootFCB (DeviceExt);
ExReleaseResourceLite (&DeviceExt->DirResource);
FileOffset.QuadPart = 0;
if (CcMapData(pFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
{
while (TRUE)
{
if (vfatIsDirEntryVolume(Entry))
if (ENTRY_VOLUME(Entry))
{
/* copy volume label */
vfat8Dot3ToVolumeLabel (Entry, Vpb->VolumeLabel);
Vpb->VolumeLabelLength = wcslen (Vpb->VolumeLabel) * sizeof(WCHAR);
vfat8Dot3ToString (Entry, &NameU);
Vpb->VolumeLabelLength = NameU.Length;
break;
}
if (vfatIsDirEntryEndMarker(Entry))
if (ENTRY_END(Entry))
{
break;
}
@ -162,242 +155,183 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
CcUnpinData(Context);
}
}
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
vfatReleaseFCB (DeviceExt, pFcb);
ExReleaseResourceLite (&DeviceExt->DirResource);
return STATUS_SUCCESS;
}
NTSTATUS
FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Fcb,
PVFATFCB Parent,
PWSTR FileToFind,
ULONG *pDirIndex,
ULONG *pDirIndex2)
PUNICODE_STRING FileToFindU,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First)
/*
* FUNCTION: Find a file
*/
{
WCHAR name[256];
WCHAR name2[14];
WCHAR TempStr[2];
WCHAR PathNameBuffer[MAX_PATH];
NTSTATUS Status;
ULONG len;
ULONG DirIndex;
ULONG FirstCluster;
BOOL isRoot;
PVOID Context = NULL;
PVOID Page;
PVFATFCB rcFcb;
BOOLEAN FoundLong;
BOOLEAN FoundShort;
UNICODE_STRING PathNameU;
BOOLEAN WildCard;
PWCHAR curr, last;
FATDirEntry fatDirEntry;
DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
Parent, FileToFindU, DirContext->DirIndex);
DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU);
DPRINT ("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
DPRINT ("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName);
PathNameU.Buffer = PathNameBuffer;
PathNameU.Length = 0;
PathNameU.MaximumLength = sizeof(PathNameBuffer);
isRoot = FALSE;
DirIndex = 0;
if (wcslen (FileToFind) == 0)
{
CHECKPOINT;
TempStr[0] = (WCHAR) '*';
TempStr[1] = 0;
FileToFind = (PWSTR)&TempStr;
}
if (Parent)
{
FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Parent->entry);
if (DeviceExt->FatInfo.FatType == FAT32)
DirContext->LongNameU.Length = 0;
DirContext->ShortNameU.Length = 0;
/* FIXME: Use FsRtlDoesNameContainWildCards */
WildCard = FALSE;
curr = FileToFindU->Buffer;
last = FileToFindU->Buffer + FileToFindU->Length / sizeof(WCHAR);
while (curr < last)
{
if (FirstCluster == DeviceExt->FatInfo.RootCluster)
isRoot = TRUE;
}
else
{
if (FirstCluster == 1)
isRoot = TRUE;
}
}
else
isRoot = TRUE;
if (isRoot)
{
if (DeviceExt->FatInfo.FatType == FAT32)
FirstCluster = DeviceExt->FatInfo.RootCluster;
else
FirstCluster = 1;
if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
|| (FileToFind[0] == '.' && FileToFind[1] == 0))
{
/* it's root : complete essentials fields then return ok */
CHECKPOINT;
memset (Fcb, 0, sizeof (VFATFCB));
memset (Fcb->entry.Filename, ' ', 11);
CHECKPOINT;
Fcb->PathName[0]='\\';
Fcb->ObjectName = &Fcb->PathName[1];
Fcb->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
Fcb->entry.CreationDate = 0x0021; /* 1.1.1980 */
Fcb->entry.AccessDate = 0x0021;
Fcb->entry.UpdateDate = 0x0021;
if (DeviceExt->FatInfo.FatType == FAT32)
{
Fcb->entry.FirstCluster = ((PUSHORT)&FirstCluster)[0];
Fcb->entry.FirstClusterHigh = ((PUSHORT)&FirstCluster)[1];
}
else
Fcb->entry.FirstCluster = 1;
if (pDirIndex)
*pDirIndex = 0;
if (pDirIndex2)
*pDirIndex2 = 0;
DPRINT("FindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
return (STATUS_SUCCESS);
}
}
else
{
DPRINT ("Parent->entry.FileSize %x\n", Parent->entry.FileSize);
FirstCluster = vfatDirEntryGetFirstCluster (DeviceExt, &Parent->entry);
}
if (pDirIndex && (*pDirIndex))
DirIndex = *pDirIndex;
if (NULL == wcschr(FileToFind, L'?') && NULL == wcschr(FileToFind, L'*'))
{
/* if there is no '*?' in the search name, than look first for an existing fcb */
len = wcslen(Parent->PathName);
memcpy(name, Parent->PathName, len * sizeof(WCHAR));
if (!vfatFCBIsRoot(Parent))
{
name[len++] = L'\\';
}
wcscpy(name + len, FileToFind);
rcFcb = vfatGrabFCBFromTable(DeviceExt, name);
if (rcFcb)
{
if(rcFcb->startIndex >= DirIndex)
{
wcscpy(Fcb->PathName, name);
Fcb->ObjectName = &Fcb->PathName[len];
memcpy(&Fcb->entry, &rcFcb->entry, sizeof(FATDirEntry));
if (pDirIndex)
{
*pDirIndex = rcFcb->dirIndex;
}
if (pDirIndex2)
{
*pDirIndex2 = rcFcb->startIndex;
}
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d (%d)\n",Fcb->PathName, Fcb->ObjectName, rcFcb->dirIndex, rcFcb->startIndex);
vfatReleaseFCB(DeviceExt, rcFcb);
return STATUS_SUCCESS;
if (*curr == L'?' || *curr == L'*')
{
WildCard = TRUE;
break;
}
else
{
vfatReleaseFCB(DeviceExt, rcFcb);
return STATUS_UNSUCCESSFUL;
curr++;
}
if (WildCard == FALSE)
{
/* if there is no '*?' in the search name, than look first for an existing fcb */
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
if (!vfatFCBIsRoot(Parent))
{
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
PathNameU.Length += sizeof(WCHAR);
}
RtlAppendUnicodeStringToString(&PathNameU, FileToFindU);
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb)
{
if(rcFcb->startIndex >= DirContext->DirIndex)
{
RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
DirContext->StartIndex = rcFcb->startIndex;
DirContext->DirIndex = rcFcb->dirIndex;
DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
&DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
Status = STATUS_SUCCESS;
}
else
{
CHECKPOINT1;
Status = STATUS_UNSUCCESSFUL;
}
vfatReleaseFCB(DeviceExt, rcFcb);
return Status;
}
vfatReleaseFCB(DeviceExt, rcFcb);
}
}
}
while(TRUE)
{
Status = vfatGetNextDirEntry(&Context, &Page, Parent, &DirIndex, name, &fatDirEntry, pDirIndex2);
if (Status == STATUS_NO_MORE_ENTRIES)
{
break;
}
if (vfatIsDirEntryVolume(&fatDirEntry))
{
DirIndex++;
continue;
}
vfat8Dot3ToString(&fatDirEntry, name2);
if (wstrcmpjoki (name, FileToFind) || wstrcmpjoki (name2, FileToFind))
{
if (Parent && Parent->PathName)
{
len = wcslen(Parent->PathName);
CHECKPOINT;
memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
Fcb->ObjectName=&Fcb->PathName[len];
if (len != 1 || Fcb->PathName[0] != '\\')
{
Fcb->ObjectName[0] = '\\';
Fcb->ObjectName = &Fcb->ObjectName[1];
}
}
else
{
Fcb->ObjectName=Fcb->PathName;
Fcb->ObjectName[0]='\\';
Fcb->ObjectName=&Fcb->ObjectName[1];
}
memcpy(&Fcb->entry, &fatDirEntry, sizeof(FATDirEntry));
wcsncpy(Fcb->ObjectName, *name == 0 ? name2 : name, MAX_PATH);
if (pDirIndex)
*pDirIndex = DirIndex;
DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex);
Status = vfatGetNextDirEntry(&Context, &Page, Parent, DirContext, First);
First = FALSE;
if (Status == STATUS_NO_MORE_ENTRIES)
{
break;
}
if (ENTRY_VOLUME(&DirContext->FatDirEntry))
{
DirContext->DirIndex++;
continue;
}
DirContext->LongNameU.Buffer[DirContext->LongNameU.Length / sizeof(WCHAR)] = 0;
DirContext->ShortNameU.Buffer[DirContext->ShortNameU.Length / sizeof(WCHAR)] = 0;
if (WildCard)
{
/* FIXME: Use FsRtlIsNameInExpression */
if (DirContext->LongNameU.Length > 0 &&
wstrcmpjoki (DirContext->LongNameU.Buffer, FileToFindU->Buffer))
{
FoundLong = TRUE;
}
else
{
FoundLong = FALSE;
}
if (FoundLong == FALSE)
{
/* FIXME: Use FsRtlIsNameInExpression */
FoundShort = wstrcmpjoki (DirContext->ShortNameU.Buffer, FileToFindU->Buffer);
}
else
{
FoundShort = FALSE;
}
}
else
{
FoundLong = RtlEqualUnicodeString(&DirContext->LongNameU, FileToFindU, TRUE);
if (FoundLong == FALSE)
{
FoundShort = RtlEqualUnicodeString(&DirContext->ShortNameU, FileToFindU, TRUE);
}
}
if (Context)
CcUnpinData(Context);
if (FoundLong || FoundShort)
{
if (WildCard)
{
RtlCopyUnicodeString(&PathNameU, &Parent->PathNameU);
if (!vfatFCBIsRoot(Parent))
{
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = L'\\';
PathNameU.Length += sizeof(WCHAR);
}
RtlAppendUnicodeStringToString(&PathNameU, &DirContext->LongNameU);
PathNameU.Buffer[PathNameU.Length / sizeof(WCHAR)] = 0;
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb != NULL)
{
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
vfatReleaseFCB(DeviceExt, rcFcb);
}
}
DPRINT("%d\n", DirContext->LongNameU.Length);
DPRINT("FindFile: new Name %wZ, DirIndex %d\n",
&DirContext->LongNameU, DirContext->DirIndex);
return STATUS_SUCCESS;
if (Context)
{
CcUnpinData(Context);
}
return STATUS_SUCCESS;
}
DirContext->DirIndex++;
}
DirIndex++;
}
if (pDirIndex)
*pDirIndex = DirIndex;
if (Context)
CcUnpinData(Context);
{
CcUnpinData(Context);
}
return (STATUS_UNSUCCESSFUL);
}
NTSTATUS
vfatMakeAbsoluteFilename (PFILE_OBJECT pFileObject,
PWSTR pRelativeFileName,
PWSTR *pAbsoluteFilename)
{
PWSTR rcName;
PVFATFCB fcb;
DPRINT ("try related for %S\n", pRelativeFileName);
fcb = pFileObject->FsContext;
assert (fcb);
/* verify related object is a directory and target name
don't start with \. */
if (!(fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
|| (pRelativeFileName[0] == L'\\'))
{
return STATUS_INVALID_PARAMETER;
}
/* construct absolute path name */
assert (wcslen (fcb->PathName) + 1 + wcslen (pRelativeFileName) + 1
<= MAX_PATH);
rcName = ExAllocatePool (NonPagedPool, MAX_PATH * sizeof(WCHAR));
if (!rcName)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
wcscpy (rcName, fcb->PathName);
if (!vfatFCBIsRoot(fcb))
wcscat (rcName, L"\\");
wcscat (rcName, pRelativeFileName);
*pAbsoluteFilename = rcName;
return STATUS_SUCCESS;
return Status;
}
NTSTATUS
VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PWSTR FileName)
PUNICODE_STRING FileNameU)
/*
* FUNCTION: Opens a file
*/
@ -405,61 +339,58 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
PVFATFCB ParentFcb;
PVFATFCB Fcb;
NTSTATUS Status;
PWSTR AbsFileName = NULL;
UNICODE_STRING NameU;
WCHAR Name[MAX_PATH];
DPRINT ("VfatOpenFile(%08lx, %08lx, %S)\n", DeviceExt, FileObject, FileName);
DPRINT ("VfatOpenFile(%08lx, %08lx, '%wZ')\n", DeviceExt, FileObject, FileNameU);
if (FileObject->RelatedFileObject)
{
DPRINT ("Converting relative filename to absolute filename\n");
Status = vfatMakeAbsoluteFilename (FileObject->RelatedFileObject,
FileName,
&AbsFileName);
FileName = AbsFileName;
if (!NT_SUCCESS(Status))
{
return Status;
}
NameU.Buffer = Name;
NameU.Length = 0;
NameU.MaximumLength = sizeof(Name);
Fcb = FileObject->RelatedFileObject->FsContext;
RtlCopyUnicodeString(&NameU, &Fcb->PathNameU);
if (!vfatFCBIsRoot(Fcb))
{
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = L'\\';
NameU.Length += sizeof(WCHAR);
}
RtlAppendUnicodeStringToString(&NameU, FileNameU);
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
FileNameU = &NameU;
}
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
DPRINT ("PathName to open: %S\n", FileName);
DPRINT ("PathName to open: '%wZ'\n", FileNameU);
/* try first to find an existing FCB in memory */
DPRINT ("Checking for existing FCB in memory\n");
Fcb = vfatGrabFCBFromTable (DeviceExt, FileName);
Fcb = vfatGrabFCBFromTable (DeviceExt, FileNameU);
if (Fcb == NULL)
{
DPRINT ("No existing FCB found, making a new one if file exists.\n");
Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileName);
if (ParentFcb != NULL)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
DPRINT ("No existing FCB found, making a new one if file exists.\n");
Status = vfatGetFCBForFile (DeviceExt, &ParentFcb, &Fcb, FileNameU);
if (ParentFcb != NULL)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
}
if (!NT_SUCCESS (Status))
{
DPRINT ("Could not make a new FCB, status: %x\n", Status);
return Status;
}
}
if (!NT_SUCCESS (Status))
{
DPRINT ("Could not make a new FCB, status: %x\n", Status);
if (AbsFileName)
ExFreePool (AbsFileName);
return Status;
}
}
if (Fcb->Flags & FCB_DELETE_PENDING)
{
vfatReleaseFCB (DeviceExt, Fcb);
if (AbsFileName)
ExFreePool (AbsFileName);
return STATUS_DELETE_PENDING;
}
{
vfatReleaseFCB (DeviceExt, Fcb);
return STATUS_DELETE_PENDING;
}
DPRINT ("Attaching FCB to fileObject\n");
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
if (AbsFileName)
ExFreePool (AbsFileName);
return Status;
}
@ -481,7 +412,7 @@ VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
}
Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0;
VfatUpdateEntry (DeviceExt, FileObject);
VfatUpdateEntry (Fcb);
if (Fcb->RFCB.FileSize.QuadPart > 0)
{
Fcb->RFCB.AllocationSize.QuadPart = 0;
@ -569,20 +500,17 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* Check for illegal characters in the file name
*/
c = FileObject->FileName.Buffer;
while (*c != 0)
c = FileObject->FileName.Buffer + FileObject->FileName.Length / sizeof(WCHAR);
while (c-- > FileObject->FileName.Buffer)
{
if (*c == L'*' || *c == L'?' || *c == L'<' || *c == L'>' ||
*c == L'/' || *c == L'|' || *c == L':' || *c == L'"' ||
(*c == L'\\' && c[1] == L'\\'))
{
return(STATUS_OBJECT_NAME_INVALID);
if (*c != '\\' && vfatIsLongIllegal(*c))
{
return(STATUS_OBJECT_NAME_INVALID);
}
c++;
}
/* Try opening the file. */
Status = VfatOpenFile (DeviceExt, FileObject, FileObject->FileName.Buffer);
Status = VfatOpenFile (DeviceExt, FileObject, &FileObject->FileName);
/*
* If the directory containing the file to open doesn't exist then
@ -607,7 +535,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
ULONG Attributes;
Attributes = Stack->Parameters.Create.FileAttributes;
Status = VfatAddEntry (DeviceExt, FileObject, RequestedOptions,
Status = VfatAddEntry (DeviceExt, &FileObject->FileName, FileObject, RequestedOptions,
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
if (NT_SUCCESS (Status))
{

View file

@ -1,9 +1,9 @@
/*
* $Id: dir.c,v 1.31 2003/08/07 11:47:32 silverblade Exp $
* $Id: dir.c,v 1.32 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/dir.c
* FILE: drivers/fs/vfat/dir.c
* PURPOSE: VFAT Filesystem : directory control
* UPDATE HISTORY:
19-12-1998 : created
@ -78,118 +78,106 @@ FsdFileTimeToDosDateTime (TIME * FileTime, WORD * pwDosDate, WORD * pwDosTime)
#define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD)))
NTSTATUS
VfatGetFileNameInformation (PVFATFCB pFcb,
PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PFILE_NAMES_INFORMATION pInfo, ULONG BufferLength)
{
ULONG Length;
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length;
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
return STATUS_SUCCESS;
}
NTSTATUS
VfatGetFileDirectoryInformation (PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
{
ULONG Length;
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
if ((sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length;
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
&pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
&pInfo->LastWriteTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
return STATUS_SUCCESS;
}
NTSTATUS
VfatGetFileFullDirectoryInformation (PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
{
ULONG Length;
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length) > BufferLength)
if ((sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length;
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + Length);
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
&pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
&pInfo->LastWriteTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate,
0, &pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
// pInfo->EaSize=;
return STATUS_SUCCESS;
}
NTSTATUS
VfatGetFileBothInformation (PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIRECTORY_INFORMATION pInfo,
ULONG BufferLength)
{
ULONG Length;
Length = wcslen (pFcb->ObjectName) * sizeof(WCHAR);
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = Length;
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length);
/*
* vfatGetDirEntryName must be called befor the long name is copyed.
* The terminating null will overwrite the first character from long name.
*/
vfatGetDirEntryName(&pFcb->entry, pInfo->ShortName);
pInfo->ShortNameLength = wcslen(pInfo->ShortName) * sizeof(WCHAR);
memcpy (pInfo->FileName, pFcb->ObjectName, Length);
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
pInfo->ShortNameLength = DirContext->ShortNameU.Length;
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToFileTime (pFcb->entry.CreationDate,
pFcb->entry.CreationTime, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (pFcb->entry.AccessDate, 0,
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationDate, &pInfo->CreationTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.AccessDate, 0,
&pInfo->LastAccessTime);
FsdDosDateTimeToFileTime (pFcb->entry.UpdateDate, pFcb->entry.UpdateTime,
&pInfo->LastWriteTime);
FsdDosDateTimeToFileTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime, &pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = pFcb->entry.FileSize;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(pFcb->entry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = pFcb->entry.Attrib;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib;
// pInfo->EaSize=;
return STATUS_SUCCESS;
}
@ -204,148 +192,178 @@ NTSTATUS DoQuery (PVFAT_IRP_CONTEXT IrpContext)
unsigned char *Buffer = NULL;
PFILE_NAMES_INFORMATION Buffer0 = NULL;
PVFATFCB pFcb;
VFATFCB tmpFcb;
PVFATCCB pCcb;
BOOLEAN First = FALSE;
BOOLEAN FirstCall;
VFAT_DIRENTRY_CONTEXT DirContext;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
PEXTENDED_IO_STACK_LOCATION Stack = (PEXTENDED_IO_STACK_LOCATION) IrpContext->Stack;
pCcb = (PVFATCCB) IrpContext->FileObject->FsContext2;
pFcb = (PVFATFCB) IrpContext->FileObject->FsContext;
// determine Buffer for result :
BufferLength = Stack->Parameters.QueryDirectory.Length;
if (IrpContext->Irp->RequestorMode != KernelMode &&
IrpContext->Irp->MdlAddress == NULL &&
IrpContext->Irp->UserBuffer != NULL)
{
ProbeForWrite(IrpContext->Irp->UserBuffer, BufferLength, 1);
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!ExAcquireResourceSharedLite(&pFcb->MainResource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{
return STATUS_PENDING;
}
{
RC = VfatLockUserBuffer(IrpContext->Irp, BufferLength, IoWriteAccess);
if (NT_SUCCESS(RC))
{
RC = STATUS_PENDING;
}
return RC;
}
// Obtain the callers parameters
BufferLength = Stack->Parameters.QueryDirectory.Length;
/* Obtain the callers parameters */
pSearchPattern = Stack->Parameters.QueryDirectory.FileName;
FileInformationClass =
Stack->Parameters.QueryDirectory.FileInformationClass;
FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
if (pSearchPattern)
{
if (!pCcb->DirectorySearchPattern)
{
if (!pCcb->SearchPattern.Buffer)
{
First = TRUE;
pCcb->SearchPattern.MaximumLength = pSearchPattern->Length + sizeof(WCHAR);
pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, pCcb->SearchPattern.MaximumLength);
if (!pCcb->SearchPattern.Buffer)
{
ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&pCcb->SearchPattern, pSearchPattern);
pCcb->SearchPattern.Buffer[pCcb->SearchPattern.Length / sizeof(WCHAR)] = 0;
}
}
else if (!pCcb->SearchPattern.Buffer)
{
First = TRUE;
pCcb->DirectorySearchPattern =
ExAllocatePool(NonPagedPool, pSearchPattern->Length + sizeof(WCHAR));
if (!pCcb->DirectorySearchPattern)
{
ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
memcpy(pCcb->DirectorySearchPattern, pSearchPattern->Buffer,
pSearchPattern->Length);
pCcb->DirectorySearchPattern[pSearchPattern->Length / sizeof(WCHAR)] = 0;
pCcb->SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
pCcb->SearchPattern.Buffer = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
if (!pCcb->SearchPattern.Buffer)
{
ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
pCcb->SearchPattern.Buffer[0] = L'*';
pCcb->SearchPattern.Buffer[1] = 0;
pCcb->SearchPattern.Length = sizeof(WCHAR);
}
}
else if (!pCcb->DirectorySearchPattern)
{
First = TRUE;
pCcb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
if (!pCcb->DirectorySearchPattern)
{
ExReleaseResourceLite(&pFcb->MainResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
pCcb->DirectorySearchPattern[0] = L'*';
pCcb->DirectorySearchPattern[1] = 0;
}
if (IrpContext->Stack->Flags & SL_INDEX_SPECIFIED)
{
pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
}
{
DirContext.DirIndex = pCcb->Entry = pCcb->CurrentByteOffset.u.LowPart;
FirstCall = TRUE;
}
else if (First || (IrpContext->Stack->Flags & SL_RESTART_SCAN))
{
pCcb->Entry = 0;
}
// determine Buffer for result :
if (IrpContext->Irp->MdlAddress)
{
Buffer = MmGetSystemAddressForMdl (IrpContext->Irp->MdlAddress);
}
{
DirContext.DirIndex = pCcb->Entry = 0;
FirstCall = TRUE;
}
else
{
Buffer = IrpContext->Irp->UserBuffer;
}
DPRINT ("Buffer=%x tofind=%S\n", Buffer, pCcb->DirectorySearchPattern);
{
DirContext.DirIndex = pCcb->Entry;
FirstCall = FALSE;
}
DPRINT ("Buffer=%x tofind=%wZ\n", Buffer, &pCcb->SearchPattern);
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
tmpFcb.ObjectName = tmpFcb.PathName;
while (RC == STATUS_SUCCESS && BufferLength > 0)
{
RC = FindFile (IrpContext->DeviceExt, &tmpFcb, pFcb,
pCcb->DirectorySearchPattern, &pCcb->Entry, NULL);
DPRINT ("Found %S, RC=%x, entry %x\n", tmpFcb.ObjectName, RC, pCcb->Entry);
if (NT_SUCCESS (RC))
{
switch (FileInformationClass)
{
case FileNameInformation:
RC = VfatGetFileNameInformation (&tmpFcb,
(PFILE_NAMES_INFORMATION) Buffer, BufferLength);
break;
case FileDirectoryInformation:
RC = VfatGetFileDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
(PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength);
break;
case FileFullDirectoryInformation:
RC = VfatGetFileFullDirectoryInformation (&tmpFcb, IrpContext->DeviceExt,
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer, BufferLength);
break;
case FileBothDirectoryInformation:
RC = VfatGetFileBothInformation (&tmpFcb, IrpContext->DeviceExt,
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer, BufferLength);
break;
default:
RC = STATUS_INVALID_INFO_CLASS;
}
if (RC == STATUS_BUFFER_OVERFLOW)
{
if (Buffer0)
RC = FindFile (IrpContext->DeviceExt, pFcb,
&pCcb->SearchPattern, &DirContext, FirstCall);
pCcb->Entry = DirContext.DirIndex;
DPRINT ("Found %wZ, RC=%x, entry %x\n", &DirContext.LongNameU, RC, pCcb->Entry);
FirstCall = FALSE;
if (NT_SUCCESS (RC))
{
Buffer0->NextEntryOffset = 0;
}
break;
}
}
else
{
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
if (First)
{
RC = STATUS_NO_SUCH_FILE;
}
switch (FileInformationClass)
{
case FileNameInformation:
RC = VfatGetFileNameInformation (&DirContext,
(PFILE_NAMES_INFORMATION) Buffer,
BufferLength);
break;
case FileDirectoryInformation:
RC = VfatGetFileDirectoryInformation (&DirContext,
IrpContext->DeviceExt,
(PFILE_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break;
case FileFullDirectoryInformation:
RC = VfatGetFileFullDirectoryInformation (&DirContext,
IrpContext->DeviceExt,
(PFILE_FULL_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break;
case FileBothDirectoryInformation:
RC = VfatGetFileBothInformation (&DirContext,
IrpContext->DeviceExt,
(PFILE_BOTH_DIRECTORY_INFORMATION) Buffer,
BufferLength);
break;
default:
RC = STATUS_INVALID_INFO_CLASS;
}
if (RC == STATUS_BUFFER_OVERFLOW)
{
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
break;
}
}
else
{
RC = STATUS_NO_MORE_FILES;
}
break;
{
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
if (First)
{
RC = STATUS_NO_SUCH_FILE;
}
else
{
RC = STATUS_NO_MORE_FILES;
}
break;
}
Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
Buffer0->FileIndex = FileIndex++;
pCcb->Entry = ++DirContext.DirIndex;
if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{
break;
}
BufferLength -= Buffer0->NextEntryOffset;
Buffer += Buffer0->NextEntryOffset;
}
Buffer0 = (PFILE_NAMES_INFORMATION) Buffer;
Buffer0->FileIndex = FileIndex++;
pCcb->Entry++;
if (IrpContext->Stack->Flags & SL_RETURN_SINGLE_ENTRY)
{
break;
}
BufferLength -= Buffer0->NextEntryOffset;
Buffer += Buffer0->NextEntryOffset;
}
if (Buffer0)
{
Buffer0->NextEntryOffset = 0;
}
{
Buffer0->NextEntryOffset = 0;
}
if (FileIndex > 0)
{
RC = STATUS_SUCCESS;
}
{
RC = STATUS_SUCCESS;
}
ExReleaseResourceLite(&pFcb->MainResource);
return RC;
}

View file

@ -1,4 +1,4 @@
/* $Id: direntry.c,v 1.14 2003/07/24 20:52:58 chorns Exp $
/* $Id: direntry.c,v 1.15 2003/10/11 17:51:56 hbirr Exp $
*
*
* FILE: DirEntry.c
@ -7,6 +7,7 @@
* PROJECT: ReactOS kernel
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Rex Jolliff (rex@lvcablemodem.com)
* Hartmut Birr
*/
/* ------------------------------------------------------- INCLUDES */
@ -41,44 +42,64 @@ vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
return cluster;
}
BOOL
vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry)
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
{
return pFatDirEntry->Filename [0] == 0xe5;
}
LARGE_INTEGER FileOffset;
PVOID Context = NULL;
PFAT_DIR_ENTRY FatDirEntry;
ULONG Index, MaxIndex;
BOOL
vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry)
{
return pFatDirEntry->Filename [0] == 0;
}
if (vfatFCBIsRoot(Fcb))
{
Index = 0;
}
else
{
Index = 2;
}
BOOL
vfatIsDirEntryLongName (FATDirEntry * pFatDirEntry)
{
return pFatDirEntry->Attrib == 0x0f;
}
FileOffset.QuadPart = 0LL;
MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
BOOL
vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry)
{
return 0x08 == (pFatDirEntry->Attrib & 0x1f);
while (Index < MaxIndex)
{
if (Context == NULL || (Index % ENTRIES_PER_PAGE) == 0)
{
if (Context != NULL)
{
CcUnpinData(Context);
}
if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatDirEntry))
{
return TRUE;
}
FatDirEntry += Index % ENTRIES_PER_PAGE;
}
if (ENTRY_END(FatDirEntry))
{
CcUnpinData(Context);
return TRUE;
}
if (!ENTRY_DELETED(FatDirEntry))
{
CcUnpinData(Context);
return FALSE;
}
Index++;
FatDirEntry++;
}
if (Context)
{
CcUnpinData(Context);
}
return TRUE;
}
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)
IN PVFATFCB pDirFcb,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First)
{
ULONG dirMap;
PWCHAR pName;
@ -86,13 +107,18 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
FATDirEntry * fatDirEntry;
slot * longNameEntry;
ULONG index;
UCHAR CheckSum, shortCheckSum;
USHORT i;
BOOLEAN Valid = TRUE;
BOOLEAN Back = FALSE;
*pFileName = 0;
DirContext->LongNameU.Buffer[0] = 0;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = ROUND_DOWN(*pDirIndex * sizeof(FATDirEntry), PAGE_SIZE);
FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FATDirEntry), PAGE_SIZE);
if (*pContext == NULL || (*pDirIndex % ENTRIES_PER_PAGE) == 0)
if (*pContext == NULL || (DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
{
if (*pContext != NULL)
{
@ -106,42 +132,97 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
}
fatDirEntry = (FATDirEntry*)(*pPage) + *pDirIndex % ENTRIES_PER_PAGE;
fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry;
dirMap = 0;
if (pStartIndex)
{
*pStartIndex = *pDirIndex;
}
if (First)
{
/* This is the first call to vfatGetNextDirEntry. Possible the start index points
* into a long name or points to a short name with an assigned long name.
* We must go back to the real start of the entry */
while (DirContext->DirIndex > 0 &&
!ENTRY_END(fatDirEntry) &&
!ENTRY_DELETED(fatDirEntry) &&
((!ENTRY_LONG(fatDirEntry) && !Back) ||
(ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40))))
{
DirContext->DirIndex--;
Back = TRUE;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == ENTRIES_PER_PAGE - 1)
{
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) + DirContext->DirIndex % ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry;
}
else
{
fatDirEntry--;
longNameEntry--;
}
}
if (!ENTRY_END(fatDirEntry) &&
(ENTRY_DELETED(fatDirEntry) || !ENTRY_LONG(fatDirEntry)))
{
DirContext->DirIndex++;
if ((DirContext->DirIndex % 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++;
}
}
}
DirContext->StartIndex = DirContext->DirIndex;
CheckSum = 0;
while (TRUE)
{
if (vfatIsDirEntryEndMarker(fatDirEntry))
{
{
if (ENTRY_END(fatDirEntry))
{
CcUnpinData(*pContext);
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
}
if (vfatIsDirEntryDeleted (fatDirEntry))
{
if (ENTRY_DELETED(fatDirEntry))
{
dirMap = 0;
*pFileName = 0;
if (pStartIndex)
{
*pStartIndex = *pDirIndex + 1;
}
}
DirContext->LongNameU.Buffer[0] = 0;
DirContext->StartIndex = DirContext->DirIndex + 1;
}
else
{
if (vfatIsDirEntryLongName (fatDirEntry))
{
{
if (ENTRY_LONG(fatDirEntry))
{
if (dirMap == 0)
{
DPRINT (" long name entry found at %d\n", *pDirIndex);
memset(pFileName, 0, 256 * sizeof(WCHAR));
}
{
DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
memset(DirContext->LongNameU.Buffer, 0, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
}
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
5, longNameEntry->name0_4,
@ -150,40 +231,70 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
index = (longNameEntry->id & 0x1f) - 1;
dirMap |= 1 << index;
pName = pFileName + 13 * index;
pName = DirContext->LongNameU.Buffer + 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);
}
DPRINT (" longName: [%S]\n", DirContext->LongNameU.Buffer);
if (CheckSum != longNameEntry->alias_checksum)
{
DPRINT1("Found wrong alias checksum in long name entry (first %x, current %x, %S)\n",
CheckSum, longNameEntry->alias_checksum, DirContext->LongNameU.Buffer);
Valid = FALSE;
}
}
else
{
memcpy (pDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
{
shortCheckSum = 0;
for (i = 0; i < 11; i++)
{
shortCheckSum = (((shortCheckSum & 1) << 7)
| ((shortCheckSum & 0xfe) >> 1))
+ fatDirEntry->Filename[i];
}
if (shortCheckSum != CheckSum && DirContext->LongNameU.Buffer[0])
{
DPRINT1("Checksum from long and short name is not equal (short: %x, long: %x, %S)\n",
shortCheckSum, CheckSum, DirContext->LongNameU.Buffer);
DirContext->LongNameU.Buffer[0] = 0;
}
if (Valid == FALSE)
{
DirContext->LongNameU.Buffer[0] = 0;
}
memcpy (&DirContext->FatDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
(*pDirIndex)++;
if ((*pDirIndex % ENTRIES_PER_PAGE) == 0)
{
}
}
DirContext->DirIndex++;
if ((DirContext->DirIndex % 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++;
}
}
}
}
DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR);
vfat8Dot3ToString(&DirContext->FatDirEntry, &DirContext->ShortNameU);
if (DirContext->LongNameU.Length == 0)
{
RtlCopyUnicodeString(&DirContext->LongNameU, &DirContext->ShortNameU);
}
return STATUS_SUCCESS;
}

View file

@ -1,8 +1,8 @@
/* $Id: dirwr.c,v 1.38 2003/07/24 20:52:58 chorns Exp $
/* $Id: dirwr.c,v 1.39 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/dirwr.c
* FILE: drivers/fs/vfat/dirwr.c
* PURPOSE: VFAT Filesystem : write in directory
*
*/
@ -19,59 +19,44 @@
#include "vfat.h"
const char *short_illegals=" ;+=[]',\"*\\<>/?:|";
static BOOLEAN
vfatIsShortIllegal(char c)
{
int i;
for (i = 0; short_illegals[i]; i++)
if (c == short_illegals[i])
return TRUE;
return FALSE;
}
NTSTATUS
VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
VfatUpdateEntry (PVFATFCB pFcb)
/*
* update an existing FAT entry
*/
{
PVOID Context;
PVOID Buffer;
PVFATFCB pDirFcb, pFcb;
PFAT_DIR_ENTRY PinEntry;
LARGE_INTEGER Offset;
/*
DPRINT ("updEntry PathFileName \'%S\'\n",
((PVFATCCB)(pFileObject->FsContext2))->pFcb->PathName);
*/
pFcb = (PVFATFCB)pFileObject->FsContext;
assert (pFcb);
pDirFcb = pFcb->parentFcb;
assert (pDirFcb);
assert (pFcb->parentFcb);
DPRINT ("updEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
Offset.u.HighPart = 0;
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
if (CcMapData (pDirFcb->FileObject, &Offset, sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&Buffer))
{
memcpy(Buffer, &pFcb->entry, sizeof(FATDirEntry));
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
if (CcMapData (pFcb->parentFcb->FileObject, &Offset, sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&PinEntry))
{
pFcb->Flags &= ~FCB_IS_DIRTY;
*PinEntry = pFcb->entry;
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
return STATUS_SUCCESS;
}
else
DPRINT1 ("Failed write to \'%S\'.\n", pDirFcb->PathName);
return STATUS_SUCCESS;
{
DPRINT1 ("Failed write to \'%wZ\'.\n", &pFcb->parentFcb->PathNameU);
return STATUS_UNSUCCESSFUL;
}
}
BOOLEAN
findDirSpace(PDEVICE_EXTENSION DeviceExt,
PVFATFCB pDirFcb,
ULONG nbSlots,
PULONG start)
vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
PVFATFCB pDirFcb,
ULONG nbSlots,
PULONG start)
{
/*
* try to find contiguous entries frees in directory,
@ -98,11 +83,11 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
TRUE, &Context, (PVOID*)&pFatEntry);
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
}
if (vfatIsDirEntryEndMarker(pFatEntry))
if (ENTRY_END(pFatEntry))
{
break;
}
if (vfatIsDirEntryDeleted(pFatEntry))
if (ENTRY_DELETED(pFatEntry))
{
nbFree++;
}
@ -172,6 +157,7 @@ findDirSpace(PDEVICE_EXTENSION DeviceExt,
NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject,
ULONG RequestedOptions,
UCHAR ReqAttr)
@ -179,280 +165,191 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
create a new FAT entry
*/
{
WCHAR DirName[MAX_PATH], *FileName, *PathFileName;
VFATFCB FileFcb;
PVOID Context = NULL;
FATDirEntry *pFatEntry, *pEntry;
FATDirEntry *pFatEntry;
slot *pSlots;
short nbSlots = 0, nbFree = 0, j, posCar, NameLen;
short nbSlots = 0, j, posCar;
PUCHAR Buffer;
BOOLEAN needTilde = FALSE, needLong = FALSE;
BOOLEAN lCaseBase, uCaseBase, lCaseExt, uCaseExt;
BOOLEAN lCaseBase = FALSE, uCaseBase, lCaseExt = FALSE, uCaseExt;
PVFATFCB newFCB;
ULONG CurrentCluster;
LARGE_INTEGER SystemTime, LocalTime, FileOffset;
NTSTATUS Status = STATUS_SUCCESS;
PVFATFCB pDirFcb;
ULONG start, size;
ULONG size;
long i;
ANSI_STRING NameA;
CHAR aName[13];
BOOLEAN IsNameLegal;
BOOLEAN SpacesFound;
PathFileName = pFileObject->FileName.Buffer;
DPRINT ("addEntry: Pathname=%S\n", PathFileName);
//find last \ in PathFileName
posCar = -1;
for (i = 0; PathFileName[i]; i++)
{
if (PathFileName[i] == L'\\')
VFAT_DIRENTRY_CONTEXT DirContext;
UNICODE_STRING DirNameU;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
DPRINT ("addEntry: Pathname='%wZ'\n", PathNameU);
vfatSplitPathName(PathNameU, &DirNameU, &DirContext.LongNameU);
if (DirNameU.Length > sizeof(WCHAR))
{
posCar = (short)i;
DirNameU.Length -= sizeof(WCHAR);
}
}
if (posCar == -1)
{
return STATUS_UNSUCCESSFUL;
}
FileName = &PathFileName[posCar + 1];
for (NameLen = 0; FileName[NameLen]; NameLen++);
// extract directory name from pathname
if (posCar == 0)
{
// root dir
DirName[0] = L'\\';
DirName[1] = 0;
}
else
{
memcpy (DirName, PathFileName, posCar * sizeof (WCHAR));
DirName[posCar] = 0;
}
// open parent directory
pDirFcb = vfatGrabFCBFromTable(DeviceExt, DirName);
pDirFcb = vfatGrabFCBFromTable(DeviceExt, &DirNameU);
if (pDirFcb == NULL)
{
return STATUS_UNSUCCESSFUL;
}
nbSlots = (NameLen + 12) / 13 + 1; //nb of entry needed for long name+normal entry
DPRINT ("NameLen= %d, nbSlots =%d\n", NameLen, nbSlots);
Buffer = ExAllocatePool (NonPagedPool, nbSlots * sizeof (FATDirEntry));
RtlZeroMemory (Buffer, nbSlots * sizeof (FATDirEntry));
pEntry = (FATDirEntry *) (Buffer + (nbSlots - 1) * sizeof (FATDirEntry));
{
return STATUS_UNSUCCESSFUL;
}
nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; //nb of entry needed for long name+normal entry
DPRINT ("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FATDirEntry));
RtlZeroMemory (Buffer, (nbSlots - 1) * sizeof (FATDirEntry));
pSlots = (slot *) Buffer;
// create 8.3 name
needTilde = FALSE;
// find last point in name
posCar = j = 0;
for (i = 0; FileName[i]; i++)
{
if (FileName[i] == '.')
{
posCar = (short)i;
if (i == j)
{
j++;
}
}
}
if (!posCar)
{
posCar = (short)i;
}
if (posCar < j)
{
posCar = (short)i;
needTilde = TRUE;
}
if (posCar > 8)
{
needTilde = TRUE;
}
//copy 8 characters max
memset (pEntry, ' ', 11);
for (i = 0, j = 0; j < 8 && i < posCar; i++)
{
if (vfatIsShortIllegal (FileName[i]))
NameA.Buffer = aName;
NameA.Length = 0;
NameA.MaximumLength = sizeof(aName);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
memset(&DirContext.FatDirEntry, 0, sizeof(FATDirEntry));
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
if (IsNameLegal == FALSE || SpacesFound != FALSE)
{
GENERATE_NAME_CONTEXT NameContext;
VFAT_DIRENTRY_CONTEXT SearchContext;
WCHAR ShortSearchName[13];
needTilde = TRUE;
pEntry->Filename[j++] = '_';
}
else
{
if (FileName[i] == '.')
{
needTilde = TRUE;
}
else
{
pEntry->Filename[j++] = toupper ((char) FileName[i]);
}
}
}
//copy extension
if (FileName[posCar])
{
for (j = 0, i = posCar + 1; FileName[i] && j < 3; i++)
{
if (vfatIsShortIllegal(FileName[i]))
{
needTilde = TRUE;
pEntry->Ext[j++] = '_';
}
else
{
if (FileName[i] == '.')
needLong = TRUE;
memset(&NameContext, 0, sizeof(GENERATE_NAME_CONTEXT));
SearchContext.LongNameU.Buffer = LongNameBuffer;
SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
SearchContext.ShortNameU.Buffer = ShortSearchName;
SearchContext.ShortNameU.MaximumLength = sizeof(ShortSearchName);
for (i = 0; i < 100; i++)
{
needTilde = TRUE;
RtlGenerate8dot3Name(&DirContext.LongNameU, FALSE, &NameContext, &DirContext.ShortNameU);
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
SearchContext.DirIndex = 0;
Status = FindFile (DeviceExt, pDirFcb, &DirContext.ShortNameU, &SearchContext, TRUE);
if (!NT_SUCCESS(Status))
{
break;
}
}
else
if (i == 100) /* FIXME : what to do after this ? */
{
pEntry->Ext[j++] = toupper ((char) (FileName[i] & 0x7F));
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
CHECKPOINT;
return STATUS_UNSUCCESSFUL;
}
}
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
aName[NameA.Length]=0;
}
}
if (FileName[i])
{
needTilde = TRUE;
}
//find good value for tilde
if (needTilde)
{
needLong = TRUE;
DPRINT ("searching a good value for tilde\n");
for (posCar = 0; posCar < 8 && pEntry->Filename[posCar] != ' '; posCar++);
if (posCar == 0) // ??????????????????????
{
pEntry->Filename[posCar++] = '_';
}
posCar += 2;
if (posCar > 8)
{
posCar = 8;
}
pEntry->Filename[posCar - 2] = '~';
pEntry->Filename[posCar - 1] = '1';
vfat8Dot3ToString (pEntry, DirName);
//try first with xxxxxx~y.zzz
for (i = 1; i < 10; i++)
{
DirName[posCar-1] = (WCHAR)('0' + i);
pEntry->Filename[posCar - 1] = (unsigned char)('0' + i);
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
if (!NT_SUCCESS(Status))
{
break;
}
}
if (i == 10)
{
posCar++;
if (posCar > 8)
{
posCar = 8;
}
pEntry->Filename[posCar - 3] = '~';
pEntry->Filename[posCar - 2] = '1';
pEntry->Filename[posCar - 1] = '0';
vfat8Dot3ToString (pEntry, DirName);
//try second with xxxxx~yy.zzz
for (i = 10; i < 100; i++)
{
DirName[posCar - 1] = '0' + i % 10;
DirName[posCar - 2] = '0' + i / 10;
pEntry->Filename[posCar - 1] = '0' + i % 10;
pEntry->Filename[posCar - 2] = '0' + i / 10;
Status = FindFile (DeviceExt, &FileFcb, pDirFcb, DirName, NULL, NULL);
if (!NT_SUCCESS(Status))
{
break;
}
}
if (i == 100) //FIXME : what to do after 99 tilde ?
{
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
return STATUS_UNSUCCESSFUL;
}
}
}
else
{
DPRINT ("check if long name entry needed, needlong=%d\n", needLong);
lCaseBase = uCaseBase = lCaseExt = uCaseExt = FALSE;
for (i = 0; i < posCar; i++)
{
if ((USHORT) tolower(pEntry->Filename[i]) == FileName[i])
{
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
lCaseBase = TRUE;
}
else if ((USHORT) pEntry->Filename[i] == FileName[i])
{
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
uCaseBase = TRUE;
}
else
{
DPRINT ("i=%d,%d,%d\n", i, pEntry->Filename[i], FileName[i]);
needLong = TRUE;
}
}
if (FileName[i])
{
i++; //jump on point char
for (j = 0, i = posCar + 1; FileName[i] && i < posCar + 4; i++, j++)
{
if ((USHORT) tolower(pEntry->Ext[j]) == FileName[i])
{
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
lCaseExt = TRUE;
}
else if ((USHORT) pEntry->Ext[j] == FileName[i])
{
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
uCaseExt = TRUE;
}
else
aName[NameA.Length] = 0;
for (posCar = 0; posCar < DirContext.LongNameU.Length / sizeof(WCHAR); posCar++)
{
if (DirContext.LongNameU.Buffer[posCar] == L'.')
{
break;
}
}
/* check if the name and the extension contains upper case characters */
RtlDowncaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
uCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
if (posCar < DirContext.LongNameU.Length/sizeof(WCHAR))
{
i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
uCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
}
else
{
uCaseExt = FALSE;
}
/* check if the name and the extension contains lower case characters */
RtlUpcaseUnicodeString(&DirContext.ShortNameU, &DirContext.LongNameU, FALSE);
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
lCaseBase = wcsncmp(DirContext.LongNameU.Buffer,
DirContext.ShortNameU.Buffer, posCar) ? TRUE : FALSE;
if (posCar < DirContext.LongNameU.Length / sizeof(WCHAR))
{
i = DirContext.LongNameU.Length / sizeof(WCHAR) - posCar;
lCaseExt = wcsncmp(DirContext.LongNameU.Buffer + posCar,
DirContext.ShortNameU.Buffer + posCar, i) ? TRUE : FALSE;
}
else
{
lCaseExt = FALSE;
}
if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))
{
DPRINT ("i=%d,j=%d,%d,%d\n", i, j, pEntry->Ext[j], FileName[i]);
needLong = TRUE;
}
}
}
if ((lCaseBase && uCaseBase) || (lCaseExt && uCaseExt))
DPRINT ("'%s', '%wZ', needTilde=%d, needLong=%d\n",
aName, &DirContext.LongNameU, needTilde, needLong);
memset(DirContext.FatDirEntry.Filename, ' ', 11);
for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
{
CHECKPOINT;
needLong = TRUE;
DirContext.FatDirEntry.Filename[i] = aName[i];
}
}
if (needLong == FALSE)
{
nbSlots = 1;
memcpy (Buffer, pEntry, sizeof (FATDirEntry));
memset (pEntry, 0, sizeof (FATDirEntry));
pEntry = (FATDirEntry *) Buffer;
if (lCaseBase)
if (aName[i] == '.')
{
pEntry->lCase |= VFAT_CASE_LOWER_BASE;
i++;
for (j = 8; j < 11 && aName[i]; j++, i++)
{
DirContext.FatDirEntry.Filename[j] = aName[i];
}
}
if (lCaseExt)
if (DirContext.FatDirEntry.Filename[0] == 0xe5)
{
pEntry->lCase |= VFAT_CASE_LOWER_EXT;
DirContext.FatDirEntry.Filename[0] = 0x05;
}
if (needLong)
{
memcpy(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
memset(DirContext.LongNameU.Buffer + DirContext.LongNameU.Length / sizeof(WCHAR) + 1, 0xff,
DirContext.LongNameU.MaximumLength - DirContext.LongNameU.Length - sizeof(WCHAR));
}
}
else
{
memset (DirName, 0xff, sizeof (DirName));
memcpy (DirName, FileName, NameLen * sizeof (WCHAR));
DirName[NameLen] = 0;
}
DPRINT ("dos name=%11.11s\n", pEntry->Filename);
{
nbSlots = 1;
if (lCaseBase)
{
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_BASE;
}
if (lCaseExt)
{
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_EXT;
}
}
DPRINT ("dos name=%11.11s\n", DirContext.FatDirEntry.Filename);
/* set attributes */
pEntry->Attrib = ReqAttr;
DirContext.FatDirEntry.Attrib = ReqAttr;
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
pEntry->Attrib |= FILE_ATTRIBUTE_DIRECTORY;
}
{
DirContext.FatDirEntry.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
}
/* set dates and times */
KeQuerySystemTime (&SystemTime);
ExSystemTimeToLocalTime (&SystemTime, &LocalTime);
@ -466,142 +363,138 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
pFileObject->FileName.Buffer);
}
#endif
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &pEntry->CreationDate,
&pEntry->CreationTime);
pEntry->UpdateDate = pEntry->CreationDate;
pEntry->UpdateTime = pEntry->CreationTime;
pEntry->AccessDate = pEntry->CreationDate;
FsdFileTimeToDosDateTime ((TIME *) & LocalTime, &DirContext.FatDirEntry.CreationDate,
&DirContext.FatDirEntry.CreationTime);
DirContext.FatDirEntry.UpdateDate = DirContext.FatDirEntry.CreationDate;
DirContext.FatDirEntry.UpdateTime = DirContext.FatDirEntry.CreationTime;
DirContext.FatDirEntry.AccessDate = DirContext.FatDirEntry.CreationDate;
if (needLong)
{
// calculate checksum for 8.3 name
for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
{
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
+ pEntry->Filename[i]);
/* calculate checksum for 8.3 name */
for (pSlots[0].alias_checksum = 0, i = 0; i < 11; i++)
{
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
+ DirContext.FatDirEntry.Filename[i]);
}
/* construct slots and entry */
for (i = nbSlots - 2; i >= 0; i--)
{
DPRINT ("construct slot %d\n", i);
pSlots[i].attr = 0xf;
if (i)
{
pSlots[i].id = nbSlots - i - 1;
}
else
{
pSlots[i].id = nbSlots - i - 1 + 0x40;
}
pSlots[i].alias_checksum = pSlots[0].alias_checksum;
memcpy (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
memcpy (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
memcpy (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
}
}
//construct slots and entry
for (i = nbSlots - 2; i >= 0; i--)
{
DPRINT ("construct slot %d\n", i);
pSlots[i].attr = 0xf;
if (i)
{
pSlots[i].id = nbSlots - i - 1;
}
else
{
pSlots[i].id = nbSlots - i - 1 + 0x40;
}
pSlots[i].alias_checksum = pSlots[0].alias_checksum;
//FIXME pSlots[i].start=;
memcpy (pSlots[i].name0_4, DirName + (nbSlots - i - 2) * 13, 10);
memcpy (pSlots[i].name5_10, DirName + (nbSlots - i - 2) * 13 + 5, 12);
memcpy (pSlots[i].name11_12, DirName + (nbSlots - i - 2) * 13 + 11, 4);
}
}
//try to find nbSlots contiguous entries frees in directory
if (!findDirSpace(DeviceExt, pDirFcb, nbSlots, &start))
{
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
return STATUS_DISK_FULL;
}
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
CurrentCluster = 0xffffffff;
Status = NextCluster (DeviceExt, 0, &CurrentCluster, TRUE);
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
/* try to find nbSlots contiguous entries frees in directory */
if (!vfatFindDirSpace(DeviceExt, pDirFcb, nbSlots, &DirContext.StartIndex))
{
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_DISK_FULL;
}
if (DeviceExt->FatInfo.FatType == FAT32)
DirContext.DirIndex = DirContext.StartIndex + nbSlots - 1;
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
pEntry->FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
CurrentCluster = 0xffffffff;
Status = NextCluster (DeviceExt, 0, &CurrentCluster, TRUE);
if (CurrentCluster == 0xffffffff || !NT_SUCCESS(Status))
{
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_DISK_FULL;
}
if (DeviceExt->FatInfo.FatType == FAT32)
{
DirContext.FatDirEntry.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
}
DirContext.FatDirEntry.FirstCluster = (unsigned short)CurrentCluster;
}
pEntry->FirstCluster = (unsigned short)CurrentCluster;
}
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = start * sizeof(FATDirEntry);
if (start / size == (start + nbSlots - 1) / size)
{
// one cluster
CHECKPOINT;
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, nbSlots * sizeof(FATDirEntry));
}
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATDirEntry);
if (DirContext.StartIndex / i == DirContext.DirIndex / i)
{
/* one cluster */
CHECKPOINT;
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
TRUE, &Context, (PVOID*)&pFatEntry);
if (nbSlots > 1)
{
memcpy(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FATDirEntry));
}
memcpy(pFatEntry + (nbSlots - 1), &DirContext.FatDirEntry, sizeof(FATDirEntry));
}
else
{
// two clusters
CHECKPOINT;
size = DeviceExt->FatInfo.BytesPerCluster -
(start * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,
&Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, size);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
FileOffset.u.LowPart += size;
CcMapData (pDirFcb->FileObject, &FileOffset,
nbSlots * sizeof(FATDirEntry) - size,
TRUE, &Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, (PVOID)(Buffer + size), nbSlots * sizeof(FATDirEntry) - size);
}
{
/* two clusters */
CHECKPOINT;
size = DeviceExt->FatInfo.BytesPerCluster -
(DirContext.StartIndex * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
i = size / sizeof(FATDirEntry);
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,
&Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, size);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
FileOffset.u.LowPart += size;
CcMapData (pDirFcb->FileObject, &FileOffset,
nbSlots * sizeof(FATDirEntry) - size,
TRUE, &Context, (PVOID*)&pFatEntry);
if (nbSlots - 1 > i)
{
memcpy(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FATDirEntry));
}
memcpy(pFatEntry + nbSlots - 1 - i, &DirContext.FatDirEntry, sizeof(FATDirEntry));
}
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
// FIXME: check status
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, FileName, pEntry,
start, start + nbSlots - 1, &newFCB);
/* FIXME: check status */
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, &DirContext, &newFCB);
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
DPRINT ("new : entry=%11.11s\n", pEntry->Filename);
DPRINT ("new : entry=%11.11s\n", DirContext.FatDirEntry.Filename);
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
FileOffset.QuadPart = 0;
CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
&Context, (PVOID*)&pFatEntry);
// clear the new directory cluster
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
// create '.' and '..'
memcpy (&pFatEntry[0].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[0].Filename, ". ", 11);
memcpy (&pFatEntry[1].Attrib, &pEntry->Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[1].Filename, ".. ", 11);
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
if (DeviceExt->FatInfo.FatType == FAT32)
{
if (pFatEntry[1].FirstCluster == (DeviceExt->FatInfo.RootCluster & 0xffff) &&
pFatEntry[1].FirstClusterHigh == (DeviceExt->FatInfo.RootCluster >> 16))
{
pFatEntry[1].FirstCluster = 0;
pFatEntry[1].FirstClusterHigh = 0;
}
FileOffset.QuadPart = 0;
CcMapData (pFileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster, TRUE,
&Context, (PVOID*)&pFatEntry);
/* clear the new directory cluster */
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
/* create '.' and '..' */
memcpy (&pFatEntry[0].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[0].Filename, ". ", 11);
memcpy (&pFatEntry[1].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[1].Filename, ".. ", 11);
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
if (vfatFCBIsRoot(pDirFcb))
{
pFatEntry[1].FirstCluster = 0;
pFatEntry[1].FirstClusterHigh = 0;
}
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
else
{
if (pFatEntry[1].FirstCluster == 1)
{
pFatEntry[1].FirstCluster = 0;
}
}
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
vfatReleaseFCB (DeviceExt, pDirFcb);
ExFreePool (Buffer);
DPRINT ("addentry ok\n");
@ -609,84 +502,57 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
}
NTSTATUS
delEntry (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT pFileObject)
VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/*
* deleting an existing FAT entry
*/
{
VFATFCB Fcb;
PVFATFCB pFcb = NULL, pDirFcb = NULL;
NTSTATUS status;
PWSTR pName;
ULONG Entry = 0, startEntry, CurrentCluster, NextCluster, i;
ULONG CurrentCluster = 0, NextCluster, i;
PVOID Context = NULL;
LARGE_INTEGER Offset;
FATDirEntry* pDirEntry;
DPRINT ("delEntry PathFileName \'%S\'\n", pFileObject->FileName.Buffer);
assert (pFcb);
assert (pFcb->parentFcb);
status = vfatGetFCBForFile(DeviceExt, &pDirFcb, &pFcb,
pFileObject->FileName.Buffer);
if (pFcb != NULL)
{
vfatReleaseFCB(DeviceExt, pFcb);
}
if (!NT_SUCCESS(status))
{
if (pDirFcb != NULL)
{
vfatReleaseFCB(DeviceExt, pDirFcb);
}
return status;
}
pName = ((PVFATFCB)pFileObject->FsContext)->ObjectName;
if (*pName == L'\\')
{
pName ++;
}
status = FindFile (DeviceExt, &Fcb, pDirFcb, pName, &Entry, &startEntry);
if (NT_SUCCESS(status))
{
PVOID Context = NULL;
LARGE_INTEGER Offset;
FATDirEntry* pDirEntry;
DPRINT ("delete entry: %d to %d\n", startEntry, Entry);
Offset.u.HighPart = 0;
for (i = startEntry; i <= Entry; i++)
DPRINT ("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
DPRINT ("delete entry: %d to %d\n", pFcb->startIndex, pFcb->dirIndex);
Offset.u.HighPart = 0;
for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
{
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0)
{
if (Context)
{
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE;
CcMapData (pDirFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
&Context, (PVOID*)&pDirEntry);
}
if (Context)
{
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE;
CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
&Context, (PVOID*)&pDirEntry);
}
pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5;
if (i == Entry)
{
CurrentCluster =
if (i == pFcb->dirIndex)
{
CurrentCluster =
vfatDirEntryGetFirstCluster (DeviceExt,
&pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))]);
}
}
}
if (Context)
if (Context)
{
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
while (CurrentCluster && CurrentCluster != 0xffffffff)
while (CurrentCluster && CurrentCluster != 0xffffffff)
{
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster, FALSE);
// FIXME: check status
/* FIXME: check status */
WriteCluster(DeviceExt, CurrentCluster, 0);
CurrentCluster = NextCluster;
}
}
vfatReleaseFCB(DeviceExt, pDirFcb);
return status;
return STATUS_SUCCESS;
}
/* EOF */

View file

@ -16,10 +16,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: ea.c,v 1.3 2003/07/24 20:52:58 chorns Exp $
/* $Id: ea.c,v 1.4 2003/10/11 17:51:56 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/ea.c
* FILE: drivers/fs/vfat/ea.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)

View file

@ -1,11 +1,12 @@
/*
* $Id: fat.c,v 1.43 2003/07/24 20:52:58 chorns Exp $
* $Id: fat.c,v 1.44 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/fat.c
* FILE: drivers/fs/vfat/fat.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*
*/
@ -143,7 +144,7 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
ULONG ChunkSize;
PVOID Context = 0;
LARGE_INTEGER Offset;
PUSHORT Block;
PUSHORT Block = NULL;
ChunkSize = CACHEPAGESIZE(DeviceExt);
FatLength = (DeviceExt->FatInfo.NumberOfClusters +2 ) * 2;
@ -155,7 +156,7 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
for (i = StartCluster * 2; i < FatLength; i += 2, Block++)
{
if ((i % ChunkSize) == 0 || Context == NULL)
{
{
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
if (Context != NULL)
{
@ -168,8 +169,8 @@ FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
return STATUS_UNSUCCESSFUL;
}
CHECKPOINT;
Block = (PUSHORT)((char*)BaseAddress + i % ChunkSize);
}
Block = (PUSHORT)((char*)BaseAddress + i % ChunkSize);
}
if (*Block == 0)
{
@ -256,7 +257,7 @@ FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
ULONG ChunkSize;
PVOID Context = 0;
LARGE_INTEGER Offset;
PULONG Block;
PULONG Block = NULL;
ChunkSize = CACHEPAGESIZE(DeviceExt);
FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2) * 4;
@ -354,7 +355,7 @@ FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
* FUNCTION: Counts free clusters in a FAT16 table
*/
{
PUSHORT Block;
PUSHORT Block = NULL;
PVOID BaseAddress = NULL;
ULONG ulCount = 0;
ULONG i;
@ -400,7 +401,7 @@ FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
* FUNCTION: Counts free clusters in a FAT32 table
*/
{
PULONG Block;
PULONG Block = NULL;
PVOID BaseAddress = NULL;
ULONG ulCount = 0;
ULONG i;

View file

@ -1,12 +1,13 @@
/* $Id: fcb.c,v 1.33 2003/08/07 11:47:32 silverblade Exp $
/* $Id: fcb.c,v 1.34 2003/10/11 17:51:56 hbirr Exp $
*
*
* FILE: fcb.c
* FILE: drivers/fs/vfat/fcb.c
* PURPOSE: Routines to manipulate FCBs.
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Rex Jolliff (rex@lvcablemodem.com)
* Hartmut Birr
*/
/* ------------------------------------------------------- INCLUDES */
@ -30,35 +31,79 @@
/* -------------------------------------------------------- PUBLICS */
ULONG vfatNameHash(ULONG hash, PWCHAR name)
ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU)
{
WCHAR c;
while(c = *name++)
{
c = towlower(c);
hash = (hash + (c << 4) + (c >> 4)) * 11;
}
PWCHAR last;
PWCHAR curr;
register WCHAR c;
curr = NameU->Buffer;
last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
while(curr < last)
{
c = towlower(*curr++);
hash = (hash + (c << 4) + (c >> 4)) * 11;
}
return hash;
}
VOID
vfatSplitPathName(PUNICODE_STRING PathNameU, PUNICODE_STRING DirNameU, PUNICODE_STRING FileNameU)
{
PWCHAR pName;
DirNameU->Buffer = PathNameU->Buffer;
pName = PathNameU->Buffer + PathNameU->Length / sizeof(WCHAR) - 1;
while (*pName != L'\\' && pName > PathNameU->Buffer)
{
pName--;
}
assert(*pName == L'\\');
FileNameU->Buffer = pName + 1;
DirNameU->Length = (FileNameU->Buffer - PathNameU->Buffer) * sizeof(WCHAR);
DirNameU->MaximumLength = DirNameU->Length;
FileNameU->Length = PathNameU->Length - DirNameU->Length;
FileNameU->MaximumLength = FileNameU->Length;
}
VOID
vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU)
{
Fcb->PathNameU.Length = 0;
Fcb->PathNameU.Buffer = Fcb->PathNameBuffer;
Fcb->PathNameU.MaximumLength = sizeof(Fcb->PathNameBuffer);
Fcb->ShortNameU.Length = 0;
Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
Fcb->ShortNameU.MaximumLength = sizeof(Fcb->ShortNameBuffer);
Fcb->DirNameU.Buffer = Fcb->PathNameU.Buffer;
if (NameU && NameU->Length)
{
RtlCopyUnicodeString(&Fcb->PathNameU, NameU);
vfatSplitPathName(&Fcb->PathNameU, &Fcb->DirNameU, &Fcb->LongNameU);
}
else
{
Fcb->DirNameU.Buffer = Fcb->LongNameU.Buffer = NULL;
Fcb->DirNameU.MaximumLength = Fcb->DirNameU.Length = 0;
Fcb->LongNameU.MaximumLength = Fcb->LongNameU.Length = 0;
}
}
PVFATFCB
vfatNewFCB(PWCHAR pFileName)
vfatNewFCB(PUNICODE_STRING pFileNameU)
{
PVFATFCB rcFCB;
DPRINT("'%wZ'\n", pFileNameU);
rcFCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->FcbLookasideList);
memset (rcFCB, 0, sizeof (VFATFCB));
if (pFileName)
{
wcscpy (rcFCB->PathName, pFileName);
rcFCB->ObjectName = wcsrchr(rcFCB->PathName, L'\\');
if (rcFCB->ObjectName == NULL)
if (rcFCB == NULL)
{
rcFCB->ObjectName = rcFCB->PathName;
return NULL;
}
rcFCB->Hash.Hash = vfatNameHash(0, rcFCB->PathName);
DPRINT("%08x (%03x) '%S'\n", rcFCB->Hash.Hash, rcFCB->Hash.Hash % FCB_HASH_TABLE_SIZE, pFileName);
}
memset(rcFCB, 0, sizeof(VFATFCB));
vfatInitFcb(rcFCB, pFileNameU);
rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
rcFCB->Hash.self = rcFCB;
rcFCB->ShortHash.self = rcFCB;
ExInitializeResourceLite(&rcFCB->PagingIoResource);
@ -70,15 +115,15 @@ vfatNewFCB(PWCHAR pFileName)
VOID
vfatDestroyCCB(PVFATCCB pCcb)
{
if (pCcb->DirectorySearchPattern)
{
ExFreePool(pCcb->DirectorySearchPattern);
}
if (pCcb->SearchPattern.Buffer)
{
ExFreePool(pCcb->SearchPattern.Buffer);
}
ExFreeToNPagedLookasideList(&VfatGlobalData->CcbLookasideList, pCcb);
}
VOID
vfatDestroyFCB(PVFATFCB pFCB)
vfatDestroyFCB(PVFATFCB pFCB)
{
FsRtlUninitializeFileLock(&pFCB->FileLock);
ExDeleteResourceLite(&pFCB->PagingIoResource);
@ -95,28 +140,26 @@ vfatFCBIsDirectory(PVFATFCB FCB)
BOOL
vfatFCBIsRoot(PVFATFCB FCB)
{
return FCB->PathName[0] == L'\\' && FCB->PathName[1] == 0 ? TRUE : FALSE;
return FCB->PathNameU.Length == sizeof(WCHAR) && FCB->PathNameU.Buffer[0] == L'\\' ? TRUE : FALSE;
}
VOID
vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{
KIRQL oldIrql;
HASHENTRY* entry;
ULONG Index;
ULONG ShortIndex;
PVFATFCB tmpFcb;
DPRINT ("releasing FCB at %x: %S, refCount:%d\n",
DPRINT ("releasing FCB at %x: %wZ, refCount:%d\n",
pFCB,
pFCB->PathName,
&pFCB->PathNameU,
pFCB->RefCount);
while (pFCB)
{
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
pFCB->RefCount--;
if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pFCB) || pFCB->Flags & FCB_DELETE_PENDING))
{
@ -151,7 +194,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
}
entry->next = pFCB->Hash.next;
}
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
if (vfatFCBIsDirectory(pFCB))
{
/* Uninitialize file cache if initialized for this file object. */
@ -168,7 +210,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
}
else
{
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
tmpFcb = NULL;
}
pFCB = tmpFcb;
@ -178,13 +219,12 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
VOID
vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{
KIRQL oldIrql;
ULONG Index;
ULONG ShortIndex;
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry);
pFCB->Hash.next = pVCB->FcbHashTable[Index];
@ -198,69 +238,58 @@ vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
{
pFCB->parentFcb->RefCount++;
}
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
}
PVFATFCB
vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PWSTR pFileName)
vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU)
{
KIRQL oldIrql;
PVFATFCB rcFCB;
ULONG Hash;
PWCHAR ObjectName = NULL;
ULONG len;
UNICODE_STRING DirNameU;
UNICODE_STRING FileNameU;
PUNICODE_STRING FcbNameU;
HASHENTRY* entry;
Hash = vfatNameHash(0, pFileName);
DPRINT("'%wZ'\n", PathNameU);
Hash = vfatNameHash(0, PathNameU);
KeAcquireSpinLock (&pVCB->FcbListLock, &oldIrql);
entry = pVCB->FcbHashTable[Hash % FCB_HASH_TABLE_SIZE];
if (entry)
{
vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
}
while (entry)
{
if (entry->Hash == Hash)
{
rcFCB = entry->self;
if (rcFCB->Hash.Hash == Hash)
{
/* compare the long name */
if (!_wcsicmp(pFileName, rcFCB->PathName))
{
rcFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
return rcFCB;
}
}
else
{
len = rcFCB->ObjectName - rcFCB->PathName + 1;
if (ObjectName == NULL)
{
ObjectName = wcsrchr(pFileName, L'\\');
if (ObjectName == NULL)
{
ObjectName = pFileName;
}
{
if (entry->Hash == Hash)
{
rcFCB = entry->self;
DPRINT("'%wZ' '%wZ'\n", &DirNameU, &rcFCB->DirNameU);
if (RtlEqualUnicodeString(&DirNameU, &rcFCB->DirNameU, TRUE))
{
if (rcFCB->Hash.Hash == Hash)
{
FcbNameU = &rcFCB->LongNameU;
}
else
{
ObjectName++;
}
}
/* compare the short name and the directory */
if (!_wcsicmp(ObjectName, rcFCB->ShortName) && !_wcsnicmp(pFileName, rcFCB->PathName, len))
{
rcFCB->RefCount++;
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
return rcFCB;
}
{
FcbNameU = &rcFCB->ShortNameU;
}
/* compare the file name */
DPRINT("'%wZ' '%wZ'\n", &FileNameU, FcbNameU);
if (RtlEqualUnicodeString(&FileNameU, FcbNameU, TRUE))
{
rcFCB->RefCount++;
CHECKPOINT;
return rcFCB;
}
}
}
}
entry = entry->next;
}
KeReleaseSpinLock (&pVCB->FcbListLock, oldIrql);
CHECKPOINT;
return NULL;
}
@ -310,11 +339,12 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB)
PVFATFCB FCB;
ULONG FirstCluster, CurrentCluster, Size = 0;
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING NameU;
FCB = vfatNewFCB(L"\\");
RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
FCB = vfatNewFCB(&NameU);
memset(FCB->entry.Filename, ' ', 11);
FCB->ShortName[0] = L'\\';
FCB->ShortName[1] = 0;
FCB->ShortHash.Hash = FCB->Hash.Hash;
FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
@ -351,8 +381,11 @@ PVFATFCB
vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
{
PVFATFCB FCB;
UNICODE_STRING NameU;
FCB = vfatGrabFCBFromTable (pVCB, L"\\");
RtlInitUnicodeStringFromLiteral(&NameU, L"\\");
FCB = vfatGrabFCBFromTable (pVCB, &NameU);
if (FCB == NULL)
{
FCB = vfatMakeRootFCB (pVCB);
@ -364,43 +397,45 @@ vfatOpenRootFCB(PDEVICE_EXTENSION pVCB)
NTSTATUS
vfatMakeFCBFromDirEntry(PVCB vcb,
PVFATFCB directoryFCB,
PWSTR longName,
PFAT_DIR_ENTRY dirEntry,
ULONG startIndex,
ULONG dirIndex,
PVFAT_DIRENTRY_CONTEXT DirContext,
PVFATFCB* fileFCB)
{
PVFATFCB rcFCB;
WCHAR pathName [MAX_PATH];
WCHAR entryName [14];
ULONG Size;
ULONG hash;
if (longName [0] != 0 && wcslen (directoryFCB->PathName) +
sizeof(WCHAR) + wcslen (longName) > MAX_PATH)
UNICODE_STRING NameU;
if (directoryFCB->PathNameU.Length + 2 * sizeof(WCHAR) +
+ DirContext->LongNameU.Length > MAX_PATH * sizeof(WCHAR))
{
return STATUS_OBJECT_NAME_INVALID;
}
wcscpy (pathName, directoryFCB->PathName);
NameU.Buffer = pathName;
NameU.Length = 0;
NameU.MaximumLength = sizeof(pathName);
RtlCopyUnicodeString(&NameU, &directoryFCB->PathNameU);
if (!vfatFCBIsRoot (directoryFCB))
{
wcscat (pathName, L"\\");
RtlAppendUnicodeToString(&NameU, L"\\");
}
hash = vfatNameHash(0, pathName);
vfatGetDirEntryName (dirEntry, entryName);
if (longName [0] != 0)
hash = vfatNameHash(0, &NameU);
if (DirContext->LongNameU.Length > 0)
{
wcscat (pathName, longName);
RtlAppendUnicodeStringToString(&NameU, &DirContext->LongNameU);
}
else
{
wcscat (pathName, entryName);
RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
}
rcFCB = vfatNewFCB (pathName);
memcpy (&rcFCB->entry, dirEntry, sizeof (FAT_DIR_ENTRY));
wcscpy(rcFCB->ShortName, entryName);
rcFCB->ShortHash.Hash = vfatNameHash(hash, entryName);
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
rcFCB = vfatNewFCB (&NameU);
memcpy (&rcFCB->entry, &DirContext->FatDirEntry, sizeof (FAT_DIR_ENTRY));
RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU);
rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
if (vfatFCBIsDirectory(rcFCB))
{
ULONG FirstCluster, CurrentCluster;
@ -425,8 +460,8 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
{
Size = rcFCB->entry.FileSize;
}
rcFCB->dirIndex = dirIndex;
rcFCB->startIndex = startIndex;
rcFCB->dirIndex = DirContext->DirIndex;
rcFCB->startIndex = DirContext->StartIndex;
rcFCB->RFCB.FileSize.QuadPart = Size;
rcFCB->RFCB.ValidDataLength.QuadPart = Size;
rcFCB->RFCB.AllocationSize.QuadPart = ROUND_UP(Size, vcb->FatInfo.BytesPerCluster);
@ -452,6 +487,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
newCCB = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
if (newCCB == NULL)
{
CHECKPOINT;
return STATUS_INSUFFICIENT_RESOURCES;
}
memset (newCCB, 0, sizeof (VFATCCB));
@ -461,7 +497,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
fileObject->FsContext = fcb;
fileObject->FsContext2 = newCCB;
DPRINT ("file open: fcb:%x file size: %d\n", fcb, fcb->entry.FileSize);
DPRINT ("file open: fcb:%x PathName:%wZ file size: %d\n", fcb, &fcb->PathNameU, fcb->entry.FileSize);
return STATUS_SUCCESS;
}
@ -469,92 +505,77 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
NTSTATUS
vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
PVFATFCB pDirectoryFCB,
PWSTR pFileToFind,
PUNICODE_STRING FileToFindU,
PVFATFCB * pFoundFCB)
{
ULONG directoryIndex;
ULONG startIndex;
NTSTATUS status;
WCHAR defaultFileName [2];
WCHAR currentLongName [256];
FAT_DIR_ENTRY currentDirEntry;
WCHAR currentEntryName [256];
PVOID Context = NULL;
PVOID Page;
BOOLEAN First = TRUE;
VFAT_DIRENTRY_CONTEXT DirContext;
WCHAR LongNameBuffer[MAX_PATH];
WCHAR ShortNameBuffer[13];
BOOLEAN FoundLong;
BOOLEAN FoundShort;
assert (pDeviceExt);
assert (pDirectoryFCB);
assert (pFileToFind);
assert (FileToFindU);
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%S)\n",
DPRINT ("vfatDirFindFile(VCB:%08x, dirFCB:%08x, File:%wZ)\n",
pDeviceExt,
pDirectoryFCB,
pFileToFind);
DPRINT ("Dir Path:%S\n", pDirectoryFCB->PathName);
FileToFindU);
DPRINT ("Dir Path:%wZ\n", &pDirectoryFCB->PathNameU);
// default to '.' if no filename specified
if (wcslen (pFileToFind) == 0)
{
defaultFileName [0] = L'.';
defaultFileName [1] = 0;
pFileToFind = defaultFileName;
}
DirContext.DirIndex = 0;
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.Length = 0;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.ShortNameU.Buffer = ShortNameBuffer;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
directoryIndex = 0;
while (TRUE)
{
status = vfatGetNextDirEntry(&Context,
&Page,
pDirectoryFCB,
&directoryIndex,
currentLongName,
&currentDirEntry,
&startIndex);
if (status == STATUS_NO_MORE_ENTRIES)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
DPRINT (" Index:%d longName:%S\n",
directoryIndex,
currentLongName);
if (!vfatIsDirEntryVolume(&currentDirEntry))
{
if (currentLongName [0] != L'\0' && wstrcmpjoki (currentLongName, pFileToFind))
{
DPRINT ("Match found, %S\n", currentLongName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
startIndex,
directoryIndex,
pFoundFCB);
CcUnpinData(Context);
return status;
}
else
{
vfatGetDirEntryName (&currentDirEntry, currentEntryName);
DPRINT (" entryName:%S\n", currentEntryName);
if (wstrcmpjoki (currentEntryName, pFileToFind))
status = vfatGetNextDirEntry(&Context,
&Page,
pDirectoryFCB,
&DirContext,
First);
First = FALSE;
if (status == STATUS_NO_MORE_ENTRIES)
{
DPRINT ("Match found, %S\n", currentEntryName);
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
currentLongName,
&currentDirEntry,
startIndex,
directoryIndex,
pFoundFCB);
CcUnpinData(Context);
return status;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
}
}
directoryIndex++;
if (!NT_SUCCESS(status))
{
return status;
}
DPRINT (" Index:%d longName:%wZ\n",
DirContext.DirIndex,
&DirContext.LongNameU);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
if (!ENTRY_VOLUME(&DirContext.FatDirEntry))
{
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
if (FoundLong == FALSE)
{
FoundShort = RtlEqualUnicodeString(FileToFindU, &DirContext.ShortNameU, TRUE);
}
if (FoundLong || FoundShort)
{
status = vfatMakeFCBFromDirEntry (pDeviceExt,
pDirectoryFCB,
&DirContext,
pFoundFCB);
CcUnpinData(Context);
return status;
}
}
DirContext.DirIndex++;
}
return STATUS_OBJECT_NAME_NOT_FOUND;
@ -564,127 +585,119 @@ NTSTATUS
vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB,
PVFATFCB *pFCB,
const PWSTR pFileName)
PUNICODE_STRING pFileNameU)
{
NTSTATUS status;
WCHAR pathName [MAX_PATH];
WCHAR elementName [MAX_PATH];
PWCHAR currentElement;
PVFATFCB FCB;
PVFATFCB FCB = NULL;
PVFATFCB parentFCB;
UNICODE_STRING NameU;
UNICODE_STRING RootNameU;
PWCHAR curr, prev, last;
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%S)\n",
DPRINT ("vfatGetFCBForFile (%x,%x,%x,%wZ)\n",
pVCB,
pParentFCB,
pFCB,
pFileName);
pFileNameU);
RtlInitUnicodeStringFromLiteral(&RootNameU, L"\\");
// Trivial case, open of the root directory on volume
if (pFileName [0] == L'\0' || wcscmp (pFileName, L"\\") == 0)
{
DPRINT ("returning root FCB\n");
FCB = vfatOpenRootFCB (pVCB);
*pFCB = FCB;
*pParentFCB = NULL;
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
}
currentElement = wcsrchr(pFileName, L'\\');
wcsncpy(pathName, pFileName, currentElement - pFileName);
pathName[currentElement - pFileName] = L'\0';
currentElement++;
FCB = vfatGrabFCBFromTable(pVCB, pathName);
if (FCB == NULL)
{
currentElement = pFileName + 1;
wcscpy (pathName, L"\\");
FCB = vfatOpenRootFCB (pVCB);
}
parentFCB = NULL;
// Parse filename and check each path element for existance and access
while (vfatGetNextPathElement (currentElement) != 0)
{
// Skip blank directory levels
if ((vfatGetNextPathElement (currentElement) - currentElement) == 0)
if (RtlEqualUnicodeString(pFileNameU, &RootNameU, FALSE))
{
currentElement++;
continue;
}
DPRINT ("returning root FCB\n");
DPRINT ("Parsing, currentElement:%S\n", currentElement);
DPRINT (" parentFCB:%x FCB:%x\n", parentFCB, FCB);
// descend to next directory level
if (parentFCB)
{
vfatReleaseFCB (pVCB, parentFCB);
parentFCB = 0;
}
// fail if element in FCB is not a directory
if (!vfatFCBIsDirectory (FCB))
{
DPRINT ("Element in requested path is not a directory\n");
vfatReleaseFCB (pVCB, FCB);
FCB = 0;
FCB = vfatOpenRootFCB (pVCB);
*pFCB = FCB;
*pParentFCB = NULL;
*pFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
}
parentFCB = FCB;
// Extract next directory level into dirName
vfatWSubString (pathName,
pFileName,
vfatGetNextPathElement (currentElement) - pFileName);
DPRINT (" pathName:%S\n", pathName);
FCB = vfatGrabFCBFromTable (pVCB, pathName);
if (FCB == NULL)
last = curr = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1;
while (*curr != L'\\' && curr > pFileNameU->Buffer)
{
vfatWSubString (elementName,
currentElement,
vfatGetNextPathElement (currentElement) - currentElement);
DPRINT (" elementName:%S\n", elementName);
status = vfatDirFindFile (pVCB, parentFCB, elementName, &FCB);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pParentFCB = parentFCB;
*pFCB = NULL;
currentElement = vfatGetNextPathElement(currentElement);
if (*currentElement == L'\0' || vfatGetNextPathElement(currentElement + 1) == 0)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
return STATUS_OBJECT_PATH_NOT_FOUND;
}
}
else if (!NT_SUCCESS (status))
{
vfatReleaseFCB (pVCB, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return status;
}
curr--;
}
if (curr > pFileNameU->Buffer)
{
NameU.Buffer = pFileNameU->Buffer;
NameU.MaximumLength = NameU.Length = (curr - pFileNameU->Buffer - 1) * sizeof(WCHAR);
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
}
else
{
FCB = NULL;
}
if (FCB == NULL)
{
FCB = vfatOpenRootFCB(pVCB);
curr = pFileNameU->Buffer;
}
curr++;
parentFCB = NULL;
while (curr <= last)
{
if (parentFCB)
{
vfatReleaseFCB (pVCB, parentFCB);
parentFCB = 0;
}
// fail if element in FCB is not a directory
if (!vfatFCBIsDirectory (FCB))
{
DPRINT ("Element in requested path is not a directory\n");
vfatReleaseFCB (pVCB, FCB);
FCB = NULL;
*pParentFCB = NULL;
*pFCB = NULL;
return STATUS_OBJECT_PATH_NOT_FOUND;
}
parentFCB = FCB;
NameU.Buffer = pFileNameU->Buffer;
prev = curr;
while (*curr != L'\\' && curr <= last)
{
curr++;
}
NameU.MaximumLength = NameU.Length = (curr - NameU.Buffer) * sizeof(WCHAR);
FCB = vfatGrabFCBFromTable(pVCB, &NameU);
if (FCB == NULL)
{
NameU.Buffer = prev;
NameU.MaximumLength = NameU.Length = (curr - prev) * sizeof(WCHAR);
status = vfatDirFindFile(pVCB, parentFCB, &NameU, &FCB);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
*pParentFCB = parentFCB;
*pFCB = NULL;
if (curr > last)
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
return STATUS_OBJECT_PATH_NOT_FOUND;
}
}
else if (!NT_SUCCESS (status))
{
vfatReleaseFCB (pVCB, parentFCB);
*pParentFCB = NULL;
*pFCB = NULL;
return status;
}
}
curr++;
}
currentElement = vfatGetNextPathElement (currentElement);
}
*pParentFCB = parentFCB;
*pFCB = FCB;
return STATUS_SUCCESS;
}

View file

@ -1,10 +1,11 @@
/* $Id: finfo.c,v 1.33 2003/09/20 20:31:57 weiden Exp $
/* $Id: finfo.c,v 1.34 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/finfo.c
* FILE: drivers/fs/vfat/finfo.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*
*/
@ -119,7 +120,7 @@ VfatSetBasicInformation(PFILE_OBJECT FileObject,
FILE_ATTRIBUTE_READONLY)));
DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
VfatUpdateEntry(DeviceExt, FileObject);
VfatUpdateEntry(FCB);
return(STATUS_SUCCESS);
}
@ -170,10 +171,6 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject,
PFILE_DISPOSITION_INFORMATION DispositionInfo)
{
KIRQL oldIrql;
VFATFCB tmpFcb;
WCHAR star[2];
ULONG Index;
NTSTATUS Status = STATUS_SUCCESS;
int count;
@ -185,60 +182,53 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
assert (DeviceExt->FatInfo.BytesPerCluster != 0);
assert (FCB != NULL);
if (!wcscmp(FCB->PathName, L"\\") || !wcscmp(FCB->ObjectName, L"..")
|| !wcscmp(FCB->ObjectName, L"."))
{
// we cannot delete a '.', '..' or the root directory
return STATUS_ACCESS_DENIED;
}
if (vfatFCBIsRoot(FCB) ||
(FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
(FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
{
// we cannot delete a '.', '..' or the root directory
return STATUS_ACCESS_DENIED;
}
if (DispositionInfo->DoDeleteFile)
{
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{
KeAcquireSpinLock (&DeviceExt->FcbListLock, &oldIrql);
count = FCB->RefCount;
if (FCB->RefCount > 1)
{
DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer));
Status = STATUS_ACCESS_DENIED;
}
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{
count = FCB->RefCount;
if (FCB->RefCount > 1)
{
DPRINT1("%d %x\n", FCB->RefCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer));
Status = STATUS_ACCESS_DENIED;
}
else
{
FCB->Flags |= FCB_DELETE_PENDING;
FileObject->DeletePending = TRUE;
}
}
else
{
FCB->Flags |= FCB_DELETE_PENDING;
FileObject->DeletePending = TRUE;
}
KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
}
else
{
DPRINT1("MmFlushImageSection returned FALSE\n");
Status = STATUS_ACCESS_DENIED;
}
DPRINT("RefCount:%d\n", count);
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
{
memset (&tmpFcb, 0, sizeof(VFATFCB));
tmpFcb.ObjectName = tmpFcb.PathName;
star[0] = L'*';
star[1] = 0;
// skip '.' and '..', start by 2
Index = 2;
Status = FindFile (DeviceExt, &tmpFcb, FCB, star, &Index, NULL);
if (NT_SUCCESS(Status))
{
DPRINT1("found: \'%S\'\n", tmpFcb.PathName);
Status = STATUS_DIRECTORY_NOT_EMPTY;
FCB->Flags &= ~FCB_DELETE_PENDING;
FileObject->DeletePending = FALSE;
}
else
{
Status = STATUS_SUCCESS;
}
}
}
else
FileObject->DeletePending = FALSE;
{
DPRINT1("MmFlushImageSection returned FALSE\n");
Status = STATUS_ACCESS_DENIED;
}
DPRINT("RefCount:%d\n", count);
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
{
if (!VfatIsDirectoryEmpty(FCB))
{
Status = STATUS_DIRECTORY_NOT_EMPTY;
FCB->Flags &= ~FCB_DELETE_PENDING;
FileObject->DeletePending = FALSE;
}
else
{
Status = STATUS_SUCCESS;
}
}
}
else
{
FileObject->DeletePending = FALSE;
}
return Status;
}
@ -252,19 +242,18 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
* FUNCTION: Retrieve the file name information
*/
{
ULONG NameLength;
assert (NameInfo != NULL);
assert (FCB != NULL);
NameLength = wcslen(FCB->PathName) * sizeof(WCHAR);
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR))
if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR))
return STATUS_BUFFER_OVERFLOW;
NameInfo->FileNameLength = NameLength;
memcpy(NameInfo->FileName, FCB->PathName, NameLength + sizeof(WCHAR));
NameInfo->FileNameLength = FCB->PathNameU.Length;
memcpy(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
NameInfo->FileName[FCB->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_NAME_INFORMATION) + NameLength + sizeof(WCHAR));
*BufferLength -= (sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS;
}
@ -328,13 +317,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
* FUNCTION: Retrieve the all file information
*/
{
ULONG NameLength;
assert (Info);
assert (Fcb);
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR))
if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR))
return(STATUS_BUFFER_OVERFLOW);
/* Basic Information */
@ -377,10 +364,11 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
/* The IO-Manager adds this information */
/* Name Information */
Info->NameInformation.FileNameLength = NameLength;
RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathName, NameLength + sizeof(WCHAR));
Info->NameInformation.FileNameLength = Fcb->PathNameU.Length;
RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathNameU.Buffer, Fcb->PathNameU.Length);
Info->NameInformation.FileName[Fcb->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR));
*BufferLength -= (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS;
}
@ -421,6 +409,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
ULONG ClusterSize = DeviceExt->FatInfo.BytesPerCluster;
ULONG NewSize = AllocationSize->u.LowPart;
ULONG NCluster;
BOOL AllocSizeChanged = FALSE;
DPRINT("VfatSetAllocationSizeInformation()\n");
@ -438,6 +427,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
if (NewSize > Fcb->RFCB.AllocationSize.u.LowPart)
{
AllocSizeChanged = TRUE;
if (FirstCluster == 0)
{
Status = NextCluster (DeviceExt, FirstCluster, &FirstCluster, TRUE);
@ -499,6 +489,7 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
}
else if (NewSize + ClusterSize <= Fcb->RFCB.AllocationSize.u.LowPart)
{
AllocSizeChanged = TRUE;
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
if (NewSize > 0)
{
@ -531,7 +522,11 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
UpdateFileSize(FileObject, Fcb, NewSize, ClusterSize);
}
/* Update the on-disk directory entry */
VfatUpdateEntry(DeviceExt, FileObject);
Fcb->Flags |= FCB_IS_DIRTY;
if (AllocSizeChanged)
{
VfatUpdateEntry(Fcb);
}
return STATUS_SUCCESS;
}
@ -659,7 +654,7 @@ NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)
DPRINT("FileInformationClass %d\n", FileInformationClass);
DPRINT("SystemBuffer %x\n", SystemBuffer);
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
if (!ExAcquireResourceExclusiveLite(&FCB->MainResource,

View file

@ -1,4 +1,4 @@
/* $Id: flush.c,v 1.4 2003/07/24 20:52:58 chorns Exp $
/* $Id: flush.c,v 1.5 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -20,8 +20,9 @@
NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
{
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%S'\n", DeviceExt, Fcb, Fcb->PathName);
DPRINT("VfatFlushFile(DeviceExt %x, Fcb %x) for '%wZ'\n", DeviceExt, Fcb, &Fcb->PathNameU);
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, &IoStatus);
if (IoStatus.Status == STATUS_INVALID_PARAMETER)
@ -29,6 +30,14 @@ NTSTATUS VfatFlushFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb)
/* FIXME: Caching was possible not initialized */
IoStatus.Status = STATUS_SUCCESS;
}
if (Fcb->Flags & FCB_IS_DIRTY)
{
Status = VfatUpdateEntry(Fcb);
if (!NT_SUCCESS(Status))
{
IoStatus.Status = Status;
}
}
return IoStatus.Status;
}
@ -42,20 +51,41 @@ NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb)
ListEntry = DeviceExt->FcbListHead.Flink;
while (ListEntry != &DeviceExt->FcbListHead)
{
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
ListEntry = ListEntry->Flink;
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
Status = VfatFlushFile(DeviceExt, Fcb);
ExReleaseResourceLite (&Fcb->MainResource);
if (!NT_SUCCESS(Status))
{
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
ReturnStatus = Status;
}
/* FIXME: Stop flushing if this is a removable media and the media was removed */
}
{
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
ListEntry = ListEntry->Flink;
if (!vfatFCBIsDirectory(Fcb))
{
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
Status = VfatFlushFile(DeviceExt, Fcb);
ExReleaseResourceLite (&Fcb->MainResource);
if (!NT_SUCCESS(Status))
{
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
ReturnStatus = Status;
}
}
/* FIXME: Stop flushing if this is a removable media and the media was removed */
}
ListEntry = DeviceExt->FcbListHead.Flink;
while (ListEntry != &DeviceExt->FcbListHead)
{
Fcb = CONTAINING_RECORD(ListEntry, VFATFCB, FcbListEntry);
ListEntry = ListEntry->Flink;
if (vfatFCBIsDirectory(Fcb))
{
ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
Status = VfatFlushFile(DeviceExt, Fcb);
ExReleaseResourceLite (&Fcb->MainResource);
if (!NT_SUCCESS(Status))
{
DPRINT1("VfatFlushFile failed, status = %x\n", Status);
ReturnStatus = Status;
}
}
/* FIXME: Stop flushing if this is a removable media and the media was removed */
}
Fcb = (PVFATFCB) DeviceExt->FATFileObject->FsContext;
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);

View file

@ -16,11 +16,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fsctl.c,v 1.23 2003/08/27 21:28:07 dwelch Exp $
/* $Id: fsctl.c,v 1.24 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/fsctl.c
* FILE: drivers/fs/vfat/fsctl.c
* PURPOSE: VFAT Filesystem
*/
@ -214,6 +214,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
PVFATFCB VolumeFcb = NULL;
PVFATCCB Ccb = NULL;
PDEVICE_OBJECT DeviceToMount;
UNICODE_STRING NameU;
DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
@ -289,7 +290,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
DPRINT("FsDeviceObject %lx\n", DeviceObject);
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
Fcb = vfatNewFCB(NULL);
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$");
Fcb = vfatNewFCB(&NameU);
if (Fcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
@ -301,9 +303,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
memset(Ccb, 0, sizeof (VFATCCB));
wcscpy(Fcb->PathName, L"$$Fat$$");
Fcb->ObjectName = Fcb->PathName;
DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
DeviceExt->FATFileObject->FsContext = Fcb;
DeviceExt->FATFileObject->FsContext2 = Ccb;
@ -335,17 +336,15 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
ExInitializeResourceLite(&DeviceExt->DirResource);
ExInitializeResourceLite(&DeviceExt->FatResource);
KeInitializeSpinLock(&DeviceExt->FcbListLock);
InitializeListHead(&DeviceExt->FcbListHead);
RtlInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
VolumeFcb = vfatNewFCB(NULL);
VolumeFcb = vfatNewFCB(&NameU);
if (VolumeFcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
wcscpy(VolumeFcb->PathName, L"$$Volume$$");
VolumeFcb->ObjectName = VolumeFcb->PathName;
VolumeFcb->Flags = FCB_IS_VOLUME;
VolumeFcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.Sectors * DeviceExt->FatInfo.BytesPerSector;
VolumeFcb->RFCB.ValidDataLength = VolumeFcb->RFCB.FileSize;

View file

@ -16,12 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: iface.c,v 1.71 2003/09/20 20:31:57 weiden Exp $
/* $Id: iface.c,v 1.72 2003/10/11 17:51:56 hbirr Exp $
*
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/iface.c
* FILE: drivers/fs/vfat/iface.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/
/* INCLUDES *****************************************************************/

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.42 2003/04/05 09:37:42 chorns Exp $
# $Id: makefile,v 1.43 2003/10/11 17:51:56 hbirr Exp $
PATH_TO_TOP = ../../..
@ -35,7 +35,13 @@ DEP_OBJECTS = $(TARGET_OBJECTS)
TARGET_CLEAN = $(DEP_FILES) *.o *.sys *.sym
TARGET_CFLAGS = -g
include $(PATH_TO_TOP)/config
ifeq ($(DBG), 1)
TARGET_CFLAGS = -Wall -Werror -g
else
TARGET_CFLAGS = -Wall -Werror -fno-strict-aliasing -O6
endif
include $(PATH_TO_TOP)/rules.mak

View file

@ -1,8 +1,8 @@
/* $Id: misc.c,v 1.10 2003/07/24 20:52:58 chorns Exp $
/* $Id: misc.c,v 1.11 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/misc.c
* FILE: drivers/fs/vfat/misc.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Hartmut Birr
*
@ -189,16 +189,16 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
VOID STDCALL VfatDoRequest (PVOID IrpContext)
{
ULONG Count = InterlockedDecrement(&QueueCount);
DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, Count);
InterlockedDecrement(&QueueCount);
DPRINT ("VfatDoRequest (IrpContext %x), MajorFunction %x, %d\n", IrpContext, ((PVFAT_IRP_CONTEXT)IrpContext)->MajorFunction, QueueCount);
VfatDispatchRequest((PVFAT_IRP_CONTEXT)IrpContext);
}
NTSTATUS VfatQueueRequest(PVFAT_IRP_CONTEXT IrpContext)
{
ULONG Count = InterlockedIncrement(&QueueCount);
DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, Count);
InterlockedIncrement(&QueueCount);
DPRINT ("VfatQueueRequest (IrpContext %x), %d\n", IrpContext, QueueCount);
assert (IrpContext != NULL);
assert (IrpContext->Irp != NULL);

View file

@ -1,11 +1,12 @@
/* $Id: rw.c,v 1.60 2003/08/07 11:47:32 silverblade Exp $
/* $Id: rw.c,v 1.61 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/rw.c
* FILE: drivers/fs/vfat/rw.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*
*/
@ -303,7 +304,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG BytesDone;
ULONG StartCluster;
ULONG ClusterCount;
NTSTATUS Status;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN First = TRUE;
ULONG BytesPerSector;
ULONG BytesPerCluster;
@ -323,9 +324,9 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, Buffer %x, "
"Length %d, WriteOffset 0x%I64x), '%S'\n", DeviceExt,
"Length %d, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, WriteOffset,
Fcb->PathName);
&Fcb->PathNameU);
assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
assert(WriteOffset.u.LowPart % BytesPerSector == 0);
@ -482,7 +483,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Fcb = IrpContext->FileObject->FsContext;
assert(Fcb);
DPRINT("<%S>\n", Fcb->PathName);
DPRINT("<%wZ>\n", &Fcb->PathNameU);
if (Fcb->Flags & FCB_IS_PAGE_FILE)
{
@ -509,7 +510,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
}
DPRINT("'%S', Offset: %d, Length %d\n", Fcb->PathName, ByteOffset.u.LowPart, Length);
DPRINT("'%wZ', Offset: %d, Length %d\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);
if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
{
@ -720,7 +721,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
Fcb = IrpContext->FileObject->FsContext;
assert(Fcb);
DPRINT("<%S>\n", Fcb->PathName);
DPRINT("<%wZ>\n", &Fcb->PathNameU);
if (Fcb->Flags & FCB_IS_PAGE_FILE)
{
@ -939,8 +940,8 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
FsdFileTimeToDosDateTime ((TIME*)&LocalTime, &Fcb->entry.UpdateDate,
&Fcb->entry.UpdateTime);
Fcb->entry.AccessDate = Fcb->entry.UpdateDate;
// update dates/times and length
VfatUpdateEntry (IrpContext->DeviceExt, IrpContext->FileObject);
/* set date and times to dirty */
Fcb->Flags |= FCB_IS_DIRTY;
}
}

View file

@ -1,8 +1,8 @@
/* $Id: shutdown.c,v 1.7 2003/07/24 20:52:58 chorns Exp $
/* $Id: shutdown.c,v 1.8 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/shutdown.c
* FILE: drivers/fs/vfat/shutdown.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
*/

View file

@ -1,10 +1,11 @@
/* $Id: string.c,v 1.11 2003/07/24 20:52:58 chorns Exp $
/* $Id: string.c,v 1.12 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/string.c
* FILE: drivers/fs/vfat/string.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*
*/
@ -20,13 +21,21 @@
/* FUNCTIONS ****************************************************************/
const WCHAR *long_illegals = L"\"*\\<>/?:|";
BOOLEAN
vfatIsLongIllegal(WCHAR c)
{
return wcschr(long_illegals, c) ? TRUE : FALSE;
}
BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
/*
* FUNCTION: Compare two wide character strings, s2 with jokers (* or ?)
* return TRUE if s1 like s2
*/
{
while ((*s2=='*')||(*s2=='?')||(towlower(*s1)==towlower(*s2)))
while ((*s2==L'*')||(*s2==L'?')||(RtlUpcaseUnicodeChar(*s1)==RtlUpcaseUnicodeChar(*s2)))
{
if ((*s1)==0 && (*s2)==0)
return(TRUE);
@ -43,54 +52,16 @@ BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
s2++;
}
}
if ((*s2)=='.')
if ((*s2)==L'.')
{
for (;((*s2)=='.')||((*s2)=='*')||((*s2)=='?');s2++) {}
for (;((*s2)==L'.')||((*s2)==L'*')||((*s2)==L'?');s2++) {}
}
if ((*s1)==0 && (*s2)==0)
return(TRUE);
return(FALSE);
}
PWCHAR
vfatGetNextPathElement (PWCHAR pFileName)
{
if (*pFileName == L'\0')
{
return 0;
}
while (*pFileName != L'\0' && *pFileName != L'\\')
{
pFileName++;
}
return pFileName;
}
void
vfatWSubString (PWCHAR pTarget, const PWCHAR pSource, size_t pLength)
{
wcsncpy (pTarget, pSource, pLength);
pTarget [pLength] = L'\0';
}
BOOL
vfatIsFileNameValid (PWCHAR pFileName)
{
PWCHAR c;
c = pFileName;
while (*c != 0)
{
if (*c == L'*' || *c == L'?')
{
return FALSE;
}
c++;
}
return TRUE;
}

View file

@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.59 2003/07/24 19:00:42 chorns Exp $ */
/* $Id: vfat.h,v 1.60 2003/10/11 17:51:56 hbirr Exp $ */
#include <ddk/ntifs.h>
@ -68,6 +68,11 @@ typedef struct _BootSector BootSector;
#define VFAT_CASE_LOWER_BASE 8 // base is lower case
#define VFAT_CASE_LOWER_EXT 16 // extension is lower case
#define ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
#define ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
struct _FATDirEntry
{
unsigned char Filename[8], Ext[3];
@ -145,6 +150,7 @@ typedef struct
KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead;
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT FATFileObject;
@ -154,7 +160,6 @@ typedef struct
BOOLEAN AvailableClustersValid;
ULONG Flags;
struct _VFATFCB * VolumeFcb;
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
LIST_ENTRY VolumeListEntry;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION, VCB, *PVCB;
@ -178,6 +183,7 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_IS_FAT 0x0004
#define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010
#define FCB_IS_DIRTY 0x0020
typedef struct _VFATFCB
{
@ -188,17 +194,26 @@ typedef struct _VFATFCB
ERESOURCE PagingIoResource;
/* end FCB header required by ROS/NT */
/* */
/* directory entry for this file or directory */
FATDirEntry entry;
/* point on filename (250 chars max) in PathName */
WCHAR *ObjectName;
/* path+filename 260 max */
WCHAR PathName[MAX_PATH];
/* long file name, points into PathNameBuffer */
UNICODE_STRING LongNameU;
/* short file name */
WCHAR ShortName[14];
UNICODE_STRING ShortNameU;
/* directory name, points into PathNameBuffer */
UNICODE_STRING DirNameU;
/* path + long file name 260 max*/
UNICODE_STRING PathNameU;
/* buffer for PathNameU */
WCHAR PathNameBuffer[MAX_PATH];
/* buffer for ShortNameU */
WCHAR ShortNameBuffer[13];
/* */
LONG RefCount;
@ -241,7 +256,7 @@ typedef struct _VFATCCB
/* for DirectoryControl */
ULONG Entry;
/* for DirectoryControl */
PWCHAR DirectorySearchPattern;
UNICODE_STRING SearchPattern;
ULONG LastCluster;
ULONG LastOffset;
@ -288,6 +303,16 @@ typedef struct
PFILE_OBJECT FileObject;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT
{
ULONG StartIndex;
ULONG DirIndex;
FAT_DIR_ENTRY FatDirEntry;
UNICODE_STRING LongNameU;
UNICODE_STRING ShortNameU;
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
/* ------------------------------------------------------ shutdown.c */
NTSTATUS STDCALL VfatShutdown (PDEVICE_OBJECT DeviceObject,
@ -336,27 +361,20 @@ NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatOpenFile (PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName);
PUNICODE_STRING FileNameU);
NTSTATUS FindFile (PDEVICE_EXTENSION DeviceExt,
PVFATFCB Fcb,
PVFATFCB Parent,
PWSTR FileToFind,
PULONG pDirIndex,
PULONG pDirIndex2);
PUNICODE_STRING FileToFindU,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
VOID vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry,
PWSTR pName);
PUNICODE_STRING NameU);
NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt,
PVPB Vpb);
BOOLEAN IsDeletedEntry (PVOID Block,
ULONG Offset);
BOOLEAN IsLastEntry (PVOID Block,
ULONG Offset);
/* --------------------------------------------------------- close.c */
NTSTATUS VfatClose (PVFAT_IRP_CONTEXT IrpContext);
@ -392,28 +410,27 @@ NTSTATUS STDCALL DriverEntry (PDRIVER_OBJECT DriverObject,
/* --------------------------------------------------------- dirwr.c */
NTSTATUS VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject,
ULONG RequestedOptions,UCHAR ReqAttr);
ULONG RequestedOptions,
UCHAR ReqAttr);
NTSTATUS VfatUpdateEntry (PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT pFileObject);
NTSTATUS VfatUpdateEntry (PVFATFCB pFcb);
NTSTATUS delEntry(PDEVICE_EXTENSION,
PFILE_OBJECT);
NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
/* -------------------------------------------------------- string.c */
VOID
vfatSplitPathName(PUNICODE_STRING PathNameU,
PUNICODE_STRING DirNameU,
PUNICODE_STRING FileNameU);
BOOLEAN vfatIsLongIllegal(WCHAR c);
BOOLEAN wstrcmpjoki (PWSTR s1,
PWSTR s2);
PWCHAR vfatGetNextPathElement (PWCHAR pFileName);
VOID vfatWSubString (PWCHAR pTarget,
const PWCHAR pSource,
size_t pLength);
BOOL vfatIsFileNameValid (PWCHAR pFileName);
/* ----------------------------------------------------------- fat.c */
NTSTATUS OffsetToCluster (PDEVICE_EXTENSION DeviceExt,
@ -443,26 +460,17 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pDirEntry);
BOOL vfatIsDirEntryDeleted (FATDirEntry * pFatDirEntry);
BOOL vfatIsDirEntryVolume (FATDirEntry * pFatDirEntry);
BOOL vfatIsDirEntryEndMarker (FATDirEntry * pFatDirEntry);
VOID vfatGetDirEntryName (PFAT_DIR_ENTRY pDirEntry,
PWSTR pEntryName);
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb);
NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN OUT PULONG pDirIndex,
OUT PWSTR pFileName,
OUT PFAT_DIR_ENTRY pDirEntry,
OUT PULONG pStartIndex);
IN PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
/* ----------------------------------------------------------- fcb.c */
PVFATFCB vfatNewFCB (PWCHAR pFileName);
PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU);
VOID vfatDestroyFCB (PVFATFCB pFCB);
@ -478,7 +486,7 @@ VOID vfatAddFCBToTable (PDEVICE_EXTENSION pVCB,
PVFATFCB pFCB);
PVFATFCB vfatGrabFCBFromTable (PDEVICE_EXTENSION pDeviceExt,
PWSTR pFileName);
PUNICODE_STRING pFileNameU);
PVFATFCB vfatMakeRootFCB (PDEVICE_EXTENSION pVCB);
@ -494,20 +502,17 @@ NTSTATUS vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
NTSTATUS vfatDirFindFile (PDEVICE_EXTENSION pVCB,
PVFATFCB parentFCB,
PWSTR elementName,
PUNICODE_STRING FileToFindU,
PVFATFCB * fileFCB);
NTSTATUS vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
PVFATFCB *pParentFCB,
PVFATFCB *pFCB,
const PWSTR pFileName);
PUNICODE_STRING pFileNameU);
NTSTATUS vfatMakeFCBFromDirEntry (PVCB vcb,
PVFATFCB directoryFCB,
PWSTR longName,
PFAT_DIR_ENTRY dirEntry,
ULONG startIndex,
ULONG dirIndex,
PVFAT_DIRENTRY_CONTEXT DirContext,
PVFATFCB * fileFCB);
/* ------------------------------------------------------------ rw.c */
@ -548,4 +553,5 @@ NTSTATUS VfatFlush(PVFAT_IRP_CONTEXT IrpContext);
NTSTATUS VfatFlushVolume(PDEVICE_EXTENSION DeviceExt, PVFATFCB VolumeFcb);
/* EOF */

View file

@ -1,10 +1,11 @@
/* $Id: volume.c,v 1.23 2003/08/07 11:47:32 silverblade Exp $
/* $Id: volume.c,v 1.24 2003/10/11 17:51:56 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/fs/vfat/volume.c
* FILE: drivers/fs/vfat/volume.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
* Hartmut Birr
*/
/* INCLUDES *****************************************************************/